Codeforces Educational Round 5
通过数: 4
Standing: 196/4176
题目链接: http://codeforces.com/contest/616
A:
两个大数,可能有首0.
问哪个数大
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <string>
#include <algorithm>
#include <iostream>
using namespace std;
const int MAXN = 1000000 + 6;
char s1[MAXN], s2[MAXN];
int main()
{
while(scanf("%s%s", s1, s2) != EOF){
int len1 = strlen(s1);
int len2 = strlen(s2);
int t1 = 0, t2 = 0;
while(s1[t1] == '0') t1++;
while(s2[t2] == '0') t2++;
if(len1 - t1 > len2 - t2) printf(">\n");
else if(len1 - t1 < len2 - t2) printf("<\n");
else{
int flag = 0;
for(int i = 0 ; i < len1 - t1 ; i++){
if(s1[i + t1] > s2[i + t2]){flag = 1; break;}
else if(s1[i + t1] < s2[i + t2]){flag = -1; break;}
}
if(flag == 1) printf(">\n");
else if(flag == -1) printf("<\n");
else printf("=\n");
}
}
return 0;
}
B:
题目写的很复杂,剥壳以后就是每一行的最小值的最大值。
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <string>
#include <algorithm>
#include <iostream>
using namespace std;
#define inf (1000000007)
const int MAXN = 100 + 5;
int c[MAXN][MAXN];
int mmax[MAXN];
int main()
{
int n, m;
while(scanf("%d%d", &n, &m) != EOF){
int ans = 0;
for(int i = 1 ; i <= n ; i++){
mmax[i] = inf;
for(int j = 1 ; j <= m ; j++) scanf("%d", &c[i][j]), mmax[i] = min(mmax[i], c[i][j]);
ans = max(ans, mmax[i]);
}
printf("%d\n", ans);
}
return 0;
}
C:
一个矩阵上,一些点空格一些点有障碍。
问对于每个障碍,如果障碍不见了,它与原先的图能够成的连通子块里面有多少个点。
把原图做一个连通分量标号,两边dfs就可以。第一遍计数,第二遍标号。
忘记输出数要%10 WA了两发
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <string>
#include <algorithm>
#include <iostream>
using namespace std;
const int MAXN = 1000 + 5;
char str[MAXN][MAXN];
int vis[MAXN][MAXN];
int cnt;
int id[MAXN][MAXN], id_cnt;
int num[MAXN * MAXN];
int n, m;
int dx[] = {-1, 0, 1, 0};
int dy[] = {0, 1, 0, -1};
bool valid(int x, int y)
{
if(x < 1 || x > n) return false;
if(y < 1 || y > m) return false;
return true;
}
void dfs1(int x, int y)
{
vis[x][y] = 1;
cnt++;
for(int i = 0 ; i < 4 ; i++){
int tx = dx[i] + x;
int ty = dy[i] + y;
if(valid(tx, ty) && vis[tx][ty] == 0 && str[tx][ty] == '.'){
dfs1(tx, ty);
}
}
}
void dfs2(int x, int y)
{
vis[x][y] = 2;
id[x][y] = id_cnt;
for(int i = 0 ; i < 4 ; i++){
int tx = dx[i] + x;
int ty = dy[i] + y;
if(valid(tx, ty) && vis[tx][ty] < 2 && str[tx][ty] == '.'){
dfs2(tx, ty);
}
}
}
int a[5];
int main()
{
while(scanf("%d%d", &n, &m) != EOF){
for(int i = 1 ; i <= n ; i++) scanf("%s", str[i] + 1);
id_cnt = 0;
memset(vis, 0, sizeof(vis));
for(int i = 1 ; i <= n ; i++){
for(int j = 1 ; j <= m ; j++){
if(vis[i][j] || str[i][j] == '*') continue;
cnt = 0;
dfs1(i, j);
num[++id_cnt] = cnt;
dfs2(i, j);
}
}
for(int i = 1 ; i <= n ; i++){
for(int j = 1 ; j <= m ; j++){
if(str[i][j] == '.') printf(".");
else{
int tcnt = 0;
a[0] = 0;
for(int k = 0 ; k < 4 ; k++){
int tx = dx[k] + i;
int ty = dy[k] + j;
if(valid(tx, ty) && str[tx][ty] == '.')
a[tcnt++] = id[tx][ty];
}
if(tcnt == 0){
printf("1");
continue;
}
sort(a, a + tcnt);
int ans = num[a[0]];
// if(i == n && j == m) printf("%d\n", ans);
for(int k = 1 ; k < tcnt ; k++){
if(a[k] != a[k - 1]) ans += num[a[k]];
// if(i == n && j == m) printf("%d\n", ans);
}
printf("%d", (ans+1) % 10);
}
}
printf("\n");
}
}
return 0;
}
D:
问最长的序列,里面不同的数不超过k个。
开头尾指针O(2*n)就可以,不明白为什么不是第三题
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <string>
#include <algorithm>
#include <iostream>
using namespace std;
const int MAXN = 1e6 + 5;
int vis[MAXN], a[MAXN];
int main()
{
int n, k;
while(scanf("%d%d", &n, &k) != EOF){
memset(vis, 0, sizeof(vis));
int cnt = 0;
int pre = 1;
int ans = 1, x, y;
x = y = 1;
for(int i = 1 ; i <= n ; i++){
scanf("%d", &a[i]);
if(vis[a[i]] == 0) cnt++;
vis[a[i]]++;
while(cnt > k && pre <= i){
vis[a[pre]]--;
if(vis[a[pre]] == 0) cnt--;
pre++;
}
if(ans < i - pre + 1) ans = i - pre + 1, x = pre, y = i;
}
printf("%d %d\n", x, y);
}
return 0;
}
E:
题意是问n%1 + n%2 + .. + n%m等于多少(n,m <= 1e13)
打表找规律,没有规律。想到了大概能转换成ans = n*m - n/i*i的形式,n/i对于一段区间是一个定数所以可以做。但是发现n/i也可能很大,然后就跪了。
标解。发现对于n/i*i,要么n/i <= sqrt(n),要么i <= sqrt(n)。故原值分为两段。I
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <string>
#include <algorithm>
#include <iostream>
using namespace std;
#define LL long long
#define mod (1000000007)
LL ppow(LL a, int x)
{
a %= mod;
LL ans = 1;
for(int i = x ; i ; i >>= 1){
if(i & 1) ans = (ans * a) % mod;
a = (a * a) % mod;
}
return ans;
}
LL mul(LL u, LL v)
{
return (u % mod) * (v % mod) % mod;
}
LL rev(LL a){return ppow(a, mod - 2);}
LL cal(LL l, LL r){return mul(mul((l + r), (r - l + 1)), rev(2));}
LL divise(LL u){return (u % mod + mod) % mod;}
int main()
{
LL n, m;
while(scanf("%I64d%I64d", &n, &m) != EOF){
LL sn = sqrt(1.0 * n);
// printf("sn = %I64d\n", sn);
LL ans = 0;
for(LL i = 1 ; i <= min(sn, m) ; i++){
ans = (ans + mul(n / i, i)) % mod;
}
// printf("ans1 = %I64d\n", ans);
// LL ans2 = 0;
// printf("sn = %I64d\n", sn);
int f = 1;
LL i = sn;
// printf("second\n");
// printf("%I64d\n", n / (i + 1) + 1);
while(n / (i + 1) + 1 <= sn){
i--;
// printf("i = %I64d", i);
// system("pause");
}
// printf("second\n");
for(; i >= 1 ; i--){
int flag = 0;
LL r = floor(1.0 * n / i);
if(r >= m) r = m, flag = 1;
LL l = floor(1.0 * n / (i + 1)) + 1;
if(l > m) break;
// if(f){
// printf("l = %I64d, r = %I64d\n", l, r);
// f = 0;
// }
// printf("i = %I64d, l = %I64d, r = %I64d, ans2 = %I64d\n", i, l, r, ans2);
ans = (ans + mul(i, cal(l, r))) % mod;
// if(flag){
// printf("i = %I64d, l = %I64d, r = %I64d\n", i, l, r);
// }
if(flag) break;
}
printf("%I64d\n", divise(mul(n, m) - ans));
}
return 0;
}
改进版
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <string>
#include <algorithm>
#include <iostream>
using namespace std;
#define LL long long
#define mod (1000000007)
#define MAXN (2000000)
LL ppow(LL a, int x)
{
a %= mod;
LL ans = 1;
for(int i = x ; i ; i >>= 1){
if(i & 1) ans = (ans * a) % mod;
a = (a * a) % mod;
}
return ans;
}
LL mul(LL u, LL v)
{
return (u % mod) * (v % mod) % mod;
}
LL rev(LL a){return ppow(a, mod - 2);}
LL cal(LL l, LL r){return mul(mul((l + r), (r - l + 1)), rev(2));}
LL divise(LL u){return (u % mod + mod) % mod;}
int main()
{
LL n, m;
while(scanf("%I64d%I64d", &n, &m) != EOF){
LL ans = 0;
LL rec = m + 1;
for(LL i = 1 ; i < MAXN ; i++){
LL l = n / (i + 1) + 1;
LL r = min(n / i, m);
if(l > r) continue;
// printf("l = %I64d, r = %I64d\n", l, r);
rec = min(l, rec);
ans = (ans + mul(i, cal(l, r))) % mod;
}
// printf("ans = %I64d\n", ans);
// printf("rec = %I64d\n", rec);
for(LL i = 1 ; i < rec ; i++){
ans = (ans + n - n % i) % mod;
}
printf("%I64d\n", divise(mul(n, m) - ans));
}
return 0;
}