Source:http://codeforces.com/contest/465
这两天真倒霉。。昨天在机房通宵准备打cf,结果迷迷糊糊忘记注册了。。赛前4分钟一看妈蛋截止了。。今天下午手贱开了下迅雷想看看校园网的速度,结果没关,2个小时把我这个月流量都走光了。。
题意:一段内存为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 }
题意:邮箱有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 }
题意:给一个串,只有前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 }
题意:三维平面上有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 }
题意:给一个数串,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 }