Codeforces Round #265 (Div. 2) 解题报告

Source:http://codeforces.com/contest/465

这两天真倒霉。。昨天在机房通宵准备打cf,结果迷迷糊糊忘记注册了。。赛前4分钟一看妈蛋截止了。。今天下午手贱开了下迅雷想看看校园网的速度,结果没关,2个小时把我这个月流量都走光了。。

 

465A inc ARG

题意:一段内存为0或1,给第一位加1,问有多少位会改变。

分析:答案是前缀连续的1的个数加上一个0,或者全是1就没有那个0。题解里有人写了些奇怪的东西看起来很厉害=。=

 1 #include<cstdio>
 2 #include<cstring>
 3 using namespace std;
 4 
 5 int n;
 6 char buf[110];
 7 int main()
 8 {
 9     scanf("%d%s", &n, buf);
10     int ans = 0;
11     while(buf[ans] == '1') ans++;
12     if (ans != n) ans++;
13     printf("%d\n", ans);
14     return 0;
15 }
View Code

 

465B Inbox (100500)

题意:邮箱有n个邮件,有的读过和没读过的,两种模式,三个操作,模式A全览所有邮件,有操作a任选一个邮件进入,模式B是查看某个邮件,操作b可以返回全览模式,或是操作c看相邻的一封邮件。问最少操作次数读完所有未读邮件。

分析:连续的一段未读邮件显然是连着看,不连续的就跳出来,再到下一段连续的。

 1 #include<cstdio>
 2 #include<cstring>
 3 using namespace std;
 4 
 5 int n, x;
 6 int main()
 7 {
 8     scanf("%d", &n);
 9     int ans = 0, pre = 0, first = 1;
10     while(n--){
11         scanf("%d", &x);
12         if (x == 1){
13             if (first){
14                 ans ++;
15                 first = 0;
16             }
17             else{
18                 if (pre == 0) ans += 2;
19                 else ans ++;
20             }
21         }
22         pre = x;
23     }
24     printf("%d\n", ans);
25     return 0;
26 }
View Code

 

464A No to Palindromes!

题意:给一个串,只有前p个字母,求长度相同,字典序比它大,且没有回文子串的最小的串。

分析:主要考虑两个问题,没有回文子串,比给定串大的字典序最小的串。考虑第一个问题,实际上有回文串的基础是aa或aba,所以对于任意i只要有string[i]不等于string[i-1]和string[i-2]即可。对于第二个问题,我一直想着用进位来弄,然后就卡住了(而且忘记还有个初始串合法的条件。。)=。=其实可以这样做,为了字典序最小,所以我们肯定是尽量保留高位的数不变,所以就从低位开始枚举,把第i位提升,如果能合法的话,肯定是有解的(p=1只有n=1有解,p=2只有n<=2有解,p=3用abc肯定能贪出解),就贪心地放后面的数,随意放,尽量小,然后输出就可以了。

 1 #include<cstdio>
 2 #include<cstring>
 3 using namespace std;
 4 
 5 int n, p;
 6 char buf[1100];
 7 char add(int i)
 8 {
 9     for (char ch = buf[i]+1; ch < 'a'+p; ch++) 
10         if (ch != buf[i-1] && ch != buf[i-2])
11             return ch;
12     return 0;
13 }
14 int main()
15 {
16     scanf("%d %d %s", &n, &p, buf+2);
17     buf[0] = buf[1] = 0;
18     for (int i = n+1; i > 1; i--){
19         int x = add(i);
20         if (x != 0){
21             buf[i] = x;
22             for (int j = i+1; j <= n+1; j++){
23                 buf[j] = 'a'-1;
24                 buf[j] = add(j);
25             }
26             buf[n+2] = 0;
27             printf("%s\n", buf+2);
28             return 0;
29         }
30     }
31     puts("NO");
32     return 0;
33 }
View Code

 

464B Restore Cube

题意:三维平面上有8个点,每个点的xyz坐标被打散了,问是否能用这8个点组成一个正方体,如果可以输出8个点xyz坐标的正确排列。

分析:首先就会想到枚举排列,那么是(3!)^8,160万左右,然后判断能否组成立方体有挺多方法,我这里用的是看任意点到其他点的距离平方,是否是3个l^2,3个2l^2,一个3l^2,如果都满足就是正方体(不会证明,感觉是个很强的条件了=。=),题解还给出了两种方案,对于任意点,看是不是刚好三个点和它距离相同且最短,然后这三条边得正交。另一种是统计所有边是否是12个l,12个sqrt(2)l,4个sqrt(3)l。反正证明都不会,也没细想。。这几种判断方法都是大概8^2,所以过题还是有点小虚。实际上我们可以固定一个点的排列,重排其他点,这样计算次数就可以除以6,千万级别,过得稳一些。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 using namespace std;
 5 
 6 typedef long long LL;
 7 int P[6][3] = {{0, 1, 2}, {0, 2, 1}, {1, 0, 2},
 8           {1, 2, 0}, {2, 0, 1}, {2, 1, 0}};
 9 LL dis[10];
10 int a[10][5], b[10][5], p[10];
11 bool findans;
12 
13 bool check()
14 {
15     for (int i = 0; i < 8; i++){
16         for (int j = 0; j < 8; j++){
17             dis[j] = 0;
18             for (int k = 0; k < 3; k++)
19                 dis[j] = dis[j] + (LL)(b[i][k]-b[j][k]) * (b[i][k]-b[j][k]);
20         }
21         sort(dis, dis+8);
22         LL len = dis[1];
23         if (len == 0) return false;
24         if (dis[1] != dis[2] || dis[1] != dis[3]) return false;
25         if (dis[4] != len * 2) return false;
26         if (dis[4] != dis[5] || dis[4] != dis[6]) return false;
27         if (dis[7] != len * 3) return false;
28     }
29     return true;
30 }
31 void dfs(int dep)
32 {
33     if (findans) return;
34     if (dep == 8){
35         for (int i = 0; i < 8; i++){
36             int id = p[i];
37             for (int j = 0; j < 3; j++){
38                 b[i][j] = a[i][P[id][j]];
39             }
40         }
41         if (check()){
42             findans = true;
43             puts("YES");
44             for (int i = 0; i < 8; i++){
45                 for (int j = 0; j < 3; j++)
46                     printf("%d%c", b[i][j], j==2?'\n':' ');
47             }
48         }
49         return;
50     }
51     for (int i = 0; i < 6; i++){
52         p[dep] = i;
53         dfs(dep+1);
54     }
55 }
56 void solve()
57 {
58     p[0] = 0;
59     findans = false;
60     dfs(1);
61     if (!findans) puts("NO");
62     return;
63 }
64 int main()
65 {
66     for (int i = 0; i < 8; i++)
67         for (int j = 0; j < 3; j++)
68             scanf("%d", &a[i][j]);
69     solve();
70     return 0;
71 }
View Code

 

464C Substitutes in Number

题意:给一个数串,n次操作,把某个数字全部替换为一个数串(数串长度和不超过10^5)。问最后的数串看成一个数,mod 10^9+7为多少。

分析:这题还真不太好写题解,都是式子,下面程序中to[i]表示数字i会变成什么串(实际上是数,即不包括前缀0),l[i]表示前面这个串的长度(包括前缀0的长度)。如果得到最终的to[0..9]和l[0..9],就可以把所给初始串展开了,具体看程序吧。。然后为了维护to[i]和l[i],需要倒序处理操作,因为正序不知道每个数接下来会变成什么。因为需要的结果是取余的,所以不用做那么大,式子只有乘法和加法,每一项大概是to[i] * 10^l[i]的形式,所以to[i]可以对10^9+7取余,这个数是质数,由费马小定理,l[i]对10^9+6取余。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #include<iostream>
 5 using namespace std;
 6 
 7 typedef long long LL;
 8 const int maxn = 100000;
 9 const int mod = (int)(1e9)+7;
10 char buf[maxn+10], tmp[maxn+10];
11 int n, x, size;
12 int b[maxn+10], q[maxn+10], st[maxn+10], ed[maxn+10];
13 LL l[maxn+10], to[maxn+10];
14 LL pow_mod(LL a, LL exp, LL mod){
15     LL ret = 1;
16     for (; exp; exp >>= 1, a = a*a % mod)
17         if (exp & 1) ret = ret * a % mod;
18     return ret;
19 }
20 int main()
21 {
22     scanf("%s %d", buf, &n);
23     size = 0;
24     for (int i = 0; i < n; i++){
25         scanf("%d-%s", &q[i], tmp);
26         int len = strlen(tmp);
27         if (len == 1){
28             st[i] = ed[i] = 0;
29             continue;
30         }
31         st[i] = size;
32         for (int j = 1; j < len; j++) b[size++] = tmp[j] - '0';
33         ed[i] = size;
34     }
35     for (int i = 0; i < 10; i++) l[i] = 1, to[i] = i;
36     for (int i = n-1; i+1; i--){
37         LL t = 0, len = 0;
38         for (int j = st[i]; j < ed[i]; j++){
39             t = (t * pow_mod(10, l[b[j]], mod) % mod + to[b[j]]) % mod;
40             len = (len + l[b[j]]) % (mod-1);
41         }
42         to[q[i]] = t, l[q[i]] = len;
43     }
44     LL ans = 0; int len = strlen(buf);
45     for (int i = 0; i < len; i++)
46         ans = (ans * pow_mod(10, l[buf[i]-'0'], mod) % mod + to[buf[i]-'0']) % mod;
47     cout << ans << endl;
48     return 0;
49 }
View Code

 

posted @ 2014-09-08 21:30  james47  阅读(305)  评论(0编辑  收藏  举报