您的位置:首页 > 其它

Codeforces Educational Round 5 ABCDE

2016-01-16 13:23 471 查看
套题链接:http://codeforces.com/contest/616

难度类型:难度上有错位,个人觉得B比A简单,D比C简单,E是数论。BD的代码量较少,AC较多。

A

题解

类型:大数,模拟

大数的比较,一开始Java大数乱搞TLE了。

然后反正就改成手写的比较,前导零忽略掉然后比长度,比字典序。

#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cstring>
#include <stack>
#include <queue>
#include <string>
#include <vector>
#include <set>
#include <map>

#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define sz(x) ((int)(x).size())
#define fi first
#define se second
using namespace std;
typedef long long LL;
typedef vector<int> VI;
typedef pair<int,int> PII;
LL powmod(LL a,LL b, LL MOD) {LL res=1;a%=MOD;for(;b;b>>=1){if(b&1)res=res*a%MOD;a=a*a%MOD;}return res;}
// head
const int N = 1e6+5;

char a
;
char b
;

int main()
{
gets(a);
gets(b);

char *sa = a, *sb = b;
while (*sa == '0') sa++;
while (*sb == '0') sb++;

int la = strlen(sa), lb = strlen(sb);
if (la != lb) {
puts(la < lb ? "<" : ">");
return 0;
}

int val = strcmp(sa, sb);

if (val < 0) {
puts("<");
} else if (val == 0) {
puts("=");
} else {
puts(">");
}
return 0;
}


B

题解

类型:模拟

每行最小值的最大值,读懂题就行了。

#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cstring>
#include <stack>
#include <queue>
#include <string>
#include <vector>
#include <set>
#include <map>

#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define sz(x) ((int)(x).size())
#define fi first
#define se second
using namespace std;
typedef long long LL;
typedef vector<int> VI;
typedef pair<int,int> PII;
LL powmod(LL a,LL b, LL MOD) {LL res=1;a%=MOD;for(;b;b>>=1){if(b&1)res=res*a%MOD;a=a*a%MOD;}return res;}
// head

int main()
{
int n, m, x, ans = 0;
scanf("%d%d", &n, &m);
for (int i = 0; i < n; i++) {
int mn = 1e9+5;
for (int j = 0; j < m; j++) {
scanf("%d", &x);
mn = min(mn, x);
}
ans = max(ans, mn);
}
printf("%d\n", ans);
return 0;
}


C

题解

类型:并查集/搜索

主流做法是搜索处理答案或用并查集合并来处理,要算的就是每个空的点的连通块大小。

我用了并查集,做答案的话就是对每个占位的点将四周的点再和它合并,我用set来做这个,因为直接在并查集里面合并会影响到并查集的结构。

#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cstring>
#include <stack>
#include <queue>
#include <string>
#include <vector>
#include <set>
#include <map>

#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define sz(x) ((int)(x).size())
#define fi first
#define se second
using namespace std;
typedef long long LL;
typedef vector<int> VI;
typedef pair<int,int> PII;
LL powmod(LL a,LL b, LL MOD) {LL res=1;a%=MOD;for(;b;b>>=1){if(b&1)res=res*a%MOD;a=a*a%MOD;}return res;}
// head
const int N = 1000+5;
const int M = 1000000+5;

int fa[M];
int cnt[M];

char s

;
int pos

;
int res

;

int find(int key) {
return (key == fa[key]) ? key : (fa[key] = find(fa[key]));
}

void init(int n) {
for (int i = 1; i <= n; i++) {
fa[i] = i;
cnt[i] = 1;
}
}

void joint(int u, int v) {
int a = find(u), b = find(v);
if (a != b) {
fa[a] = b;
cnt += cnt[a];
}
}

bool same(int u, int v) {
return find(u) == find(v);
}

int dx[4] = {0, 0, 1, -1};
int dy[4] = {1, -1, 0, 0};

int n, m;

PII mov(PII &cur, int dir) {
return mp(cur.fi+dx[dir], cur.se+dy[dir]);
}

bool isok(PII &cur) {
return cur.fi > 0 && cur.fi <= n && cur.se > 0 && cur.se <= m;
}

int main()
{
scanf("%d%d", &n, &m);
init(n*m);
for (int i = 1; i <= n; i++) {
scanf("%s", s[i]+1);
for (int j = 1; j <= m; j++) {
pos[i][j] = (i-1)*m+j;
}
}

for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
if (s[i][j] == '*') continue;
for (int dir = 0; dir < 4; dir++) {
PII to = mp(i+dx[dir], j+dy[dir]);
if (!isok(to) || s[to.fi][to.se] == '*') continue;
joint(pos[i][j], pos[to.fi][to.se]);
}
}
}

set<int> se;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
if (s[i][j] != '*') continue;
int ans = 1;
for (int dir = 0; dir < 4; dir++) {
PII to = mp(i+dx[dir], j+dy[dir]);
if (!isok(to) || s[to.fi][to.se] == '*') continue;
int temp = find(pos[to.fi][to.se]);
if (se.find(temp) == se.end()) {
ans += cnt[temp];
se.insert(temp);
}
}
res[i][j] = ans % 10;
se.clear();
}
}

for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
putchar((s[i][j] == '*') ? '0' + res[i][j] : '.');
}
puts("");
}
return 0;
}


D

题解

类型:模拟,数据维护,尺取法

数据只有六次方,非法存在传递性,因此尺取法乱搞就行了。

维护一个数组cnticnt_i表示值为ii的数当前有多少个。

移动右边的指针,找左边的最优解,同时维护cntcnt数组具体可以参照代码或者《挑战》。

#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cstring>
#include <stack>
#include <queue>
#include <string>
#include <vector>
#include <set>
#include <map>

#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define sz(x) ((int)(x).size())
#define fi first
#define se second
using namespace std;
typedef long long LL;
typedef vector<int> VI;
typedef pair<int,int> PII;
LL powmod(LL a,LL b, LL MOD) {LL res=1;a%=MOD;for(;b;b>>=1){if(b&1)res=res*a%MOD;a=a*a%MOD;}return res;}
// head
const int N = 1e6+5;

int a
;
int cnt
;

int main()
{
int k, n;
int ansl, ansr, ans = 0;
int l = 1, cur = 0;

scanf("%d%d", &n, &k);
for (int i = 1; i <= n; i++) {
scanf("%d", a+i);
if (cnt[a[i]]++ == 0) cur++;
while (cur > k) {
if (cnt[a[l]]-- == 1) cur--;
l++;
}
if (i-l+1 > ans) {
ansl = l, ansr = i, ans = i-l+1;
}
}

printf("%d %d\n", ansl, ansr);
return 0;
}


E

题解

类型:数论

求(∑i=1mnmodi)mod109+7(\sum\limits_{i=1}^{m}{n \mod i}) \mod 10^9+7

由于main函数一处乘法没有对nn取模,非常可惜没能在场上A掉,赛后五分钟一下就看到了。

具体的做法就是说分块,算等差,复杂度是对数的。此题很适合暴力对拍。

具体推导过程可看我另一篇:[b]/article/8670588.html


#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cstring>
#include <stack>
#include <queue>
#include <string>
#include <vector>
#include <set>
#include <map>

#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define sz(x) ((int)(x).size())
#define fi first
#define se second
using namespace std;
typedef long long LL;
typedef vector<int> VI;
typedef pair<int,int> PII;
LL powmod(LL a,LL b, LL MOD) {LL res=1;a%=MOD;for(;b;b>>=1){if(b&1)res=res*a%MOD;a=a*a%MOD;}return res;}
// head
const LL MOD = 1e9+7;

LL ck(LL n, LL m) {
LL ans = 0;
for (int i = 1; i <= m; i++) {
ans += (n%i);
ans %= MOD;
}
return ans;
}

LL solve(LL n, LL m) {
LL be = 1, en, mul, ans = 0;
while (be <= m) {
mul = n/be;
en = min(n/mul, m);
LL cur = n%be;
LL num = (MOD+en-be)%MOD;
ans += (MOD + cur + cur-num*mul%MOD) % MOD * (num+1) % MOD;
ans %= MOD;
be = en+1;
}
return ans * powmod(2, MOD-2, MOD) % MOD;
}

int main()
{
LL n, m;
scanf("%I64d%I64d", &n, &m);

LL ans = 0;
if (m > n) {
ans = (MOD+m-n)%MOD * (n%MOD) % MOD;
}

ans = ans+solve(n, min(m, n));
printf("%I64d\n", ans%MOD);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: