UVALive 6256 LA 6256 Who wants to live forever?

题意:给出一个只含01的字符串,然后用s(i-1) xor s(i+1)的结果去更新s(i),最后问能否将原串更新成全部为0的字符串。

一拿到就觉得这应该是找规律题,经过简单的推理,可以得到这么一些结论:

1.当字符串长度为1,3,7的时候,无论原串是什么,分别最多做1,3,7次操作,总能变成全部为0的串(YY:只要字符串的长度为2^n-1,无论原串是什么,总能变成全部为0的串)

2.当字符串长度为偶数时,除非原串本身全为0,否则不可能将原串更新为全部为0的串(这个能证出来,倒着推一下就行了,给出一个长度为偶数且全为0的串,向上推一个可行的状态,让它不仅含有1而且还可以变成全部为0的,这是不可能的)

3.当字符串长度为4n+1时,除非原串本身全为0或者为10101…………010101这样以1开始和结尾,中间01间隔的这样一种形式,否则不可能将原串更新为全部为0的串(还是跟上面一样倒推,可以推出来)

4.当字符串长度为4n+3时,状态就比较多了,显然对于4n+1的所有情况是成立的,但是由10101…………010101这样的串,还可以往上推。这好像就没什么办法了。没办法就暴力打表(当然也是倒着推来打的表),打出来看下有什么规律。。但是打出来从字符串本身来看,真的找不到什么规律。但是有一个发现,当字符串长度n=11,19的时候,可行解一共是8个,当n=23的时候,可行解突然达到了128个。再然后,可以推出来(不是看出来,当然看也能看出来),所有长度为11的可行串,在4,8这两个位置上必须为0,且1-3和5-7这两个区间是关于4位置对称的,5-7和9-11这两个区间是关于8这个位置对称的,大概就是这样一种情况:acb0bca0acb。结合刚才的两点,又可以YY了:可行解一定是关于某些位置对称的,n=11,19的时候,可行解数是8=2^3,n=23的时候,可行解数=128=2^7,继续YY,长度为11的时候,可行解的只有abc的取值决定,abc各有两个取值,结果就是2的3次=8。要是这样的话,n=23的时候,应该关于8,16这两个位置对称,可行解应该是这样一种形式:abcdefg0gfedcba0abcdefg,可行解的只有abcdefg的取值决定,abcdefg各有两个取值,结果就是2的7次=128。那么这个对称的位置的取值究竟是由什么决定的,继续YY。(11+1)%(2^2)=0,(19+1)%(2^2)=0,(23+1)%(2^3)=0,也就是说,当字符串长度=4n+3的时候,要找一个最大的k,使得(4n+3+1)%(2^k)=0,那么这些对称的位置就是所有的0<(2^k)*t<4n+3(t为整数)的位置。

以上是我们YY本题的全部过程。用这样的做法去交能AC也说明了这些YY的结果都是正确的。本题我们队集体YY了一小时,最后因为我的一个失误,在比赛的最后时刻没有A,就差了一行。。要是正式比赛出现这样的情况,是要吐血的。

看到标程,彻底Orz了。。不管字符串长度是多少,他只用到了我上面写的第4条YY的那些规则就搞定了,不过后来我想想也对,只要满足第四条的对称规则就行。

贴两份代码,一份自己写的,一份标程的

 1 #include <cstdio>
 2 #include <cstring>
 3 char S[200020];
 4 int main(){
 5     int T,len;
 6     scanf("%d",&T);
 7     while(T--){
 8         scanf("%s",S);
 9         len = strlen(S);
10         if((len&(len+1)) == 0){
11             puts("DIES");
12             continue;
13         }
14         if((len&1) == 0){
15             bool flag = 1;
16             for(int i = 0;i < len;i++){
17                 if(S[i] - '0' == 1){
18                     flag = 0;
19                     break;
20                 }
21             }
22             if(flag)    puts("DIES");
23             else        puts("LIVES");
24             continue;
25         }
26         if(len % 4 == 1){
27             bool flag = 1;
28             for(int i = 0;i < len;i++){
29                 if(S[i] - '0' == 1){
30                     flag = 0;
31                     break;
32                 }
33             }
34             if(flag){
35                 puts("DIES");
36                 continue;
37             }
38             flag = 1;
39             for(int i = 0;i < len;i++){
40                 if((i&1) == 0 && S[i] - '0' != 1){
41                     flag = 0;
42                     break;
43                 }
44                 if((i&1) == 1 && S[i] - '0' != 0){
45                     flag = 0;
46                     break;
47                 }
48             }
49             if(flag)    puts("DIES");
50             else        puts("LIVES");
51             continue;
52         }
53         if(len % 4 == 3){
54             bool flag = 1;
55             for(int i = 0;i < len;i++){
56                 if(S[i] - '0' == 1){
57                     flag = 0;
58                     break;
59                 }
60             }
61             if(flag){
62                 puts("DIES");
63                 continue;
64             }
65             flag = 1;
66             int k = 1;
67             int tmp = len+1;
68             while((tmp&1) == 0){
69                 k *= 2;
70                 tmp >>= 1;
71             }
72             for(int i = k-1;i < len;i = i+k){
73                 if(S[i] - '0' != 0){
74                     flag = 0;
75                     break;
76                 }
77                 for(int j = 1;j < k;j++){
78                     if(S[i-j] != S[i+j]){
79                         flag = 0;
80                     }
81                 }
82             }
83             if(flag)    puts("DIES");
84             else        puts("LIVES");
85         }
86     }
87     return 0;
88 }
View Code
 1 // CERC 2012
 2 // Problem B: Who wants to live forever?
 3 // O(n) solution
 4 // Author: Arkadiusz Pawlik
 5 
 6 #include <iostream>
 7 #include <string>
 8 #include <algorithm>
 9 using namespace std;
10 
11 bool die(string s) {
12     s += "0";
13     int n = s.size();
14     int l = ((n ^ (n-1)) + 1) / 2;
15     int cnt = n / l;
16     cout<<"n="<<n<<" l="<<l<<endl;
17     cout<<"cnt="<<cnt<<endl;
18     for (int i = 1; i < cnt; ++i) {
19         for (int k = 0; k < l-1; ++k) {
20             if (s[i*l+k] != s[i*l-2-k]) return false;
21         }
22         cout<<"caca:"<<s[i*l-1]<<endl;
23         if (s[i*l-1] != '0') return false;
24     }
25     return true;
26 }
27 /*
28 string ft(string s) {
29     for (int i = 0; i < s.size(); ++i) {
30         if (i % 3 == 2) continue;
31         s[i] = (s[i] == '1') ? '0' : '1';
32     }
33     return s;
34 }
35 */
36 int main() {
37     int n;
38     cin >> n;
39     while(n--) {
40         string s;
41         cin >> s;
42         if (die(s)) cout << "DIES" << endl;
43         else cout << "LIVES" << endl;
44     }
45 }
View Code

 

posted @ 2013-10-03 18:30  浙西贫农  阅读(400)  评论(0编辑  收藏  举报