Codeforces1071C Triple Flips 构造Four Russians
Posted menhera
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codeforces1071C Triple Flips 构造Four Russians相关的知识,希望对你有一定的参考价值。
题目分析:
这种题目显然可以先考虑哪些无解。我们发现我们不考虑操作次数的时候,我们可以选择连续的三个进行异或操作。
这样我们总能使得一个序列转化为$000...000xy$的形式。换句话说,对于$000...0001$,$000...0010$,$000...0011$考虑无解条件即可。
这时候写一个暴力程序,用$O(n^2*2^n)$的算法可以发现其中一个是总长小于$7$无解,另外两个是小于$8$无解。
然后观察题目要求的操作次数与$n/3$有关,不难想到每$3$个分成一组,然后在组内调成$0$,允许利用组外信息,每组只允许用一次操作。但这样操作数会超过($011 or 110$)。
那我们放宽一下限制,每$6$个分成一组,在组内调成$0$,允许利用组外信息,每组只允许操作两次。这样就可以了(我一开始以为$110111$是不行的,写了一个暴力后后来发现我脑残了)。
这样我们考虑Four Russians,预处理出来每$6$组怎么走,最后对剩余的暴力就行了。
代码:
1 #include<bits/stdc++.h> 2 using namespace std; 3 4 const int maxn = 102000; 5 6 int n,a[maxn],f[1<<12]; 7 struct node{int x,y,z;}; 8 vector <node> des[64]; 9 10 void init(){ 11 queue<int> q; 12 int N = 6; 13 memset(f,0x3f,sizeof(f)); 14 f[0] = 0; q.push(0); 15 while(!q.empty()){ 16 int k = q.front();q.pop(); 17 for(int i=0;i<N;i++){ 18 if(f[k^(1<<i)] > f[k] + 1){ 19 for(int j=0;j<des[k].size();j++) 20 des[k^(1<<i)].push_back(des[k][j]); 21 des[k^(1<<i)].push_back((node){i,6,12-i}); 22 f[k^(1<<i)] = f[k]+1; 23 q.push(k^(1<<i)); 24 } 25 for(int j=i+1;j<N;j++){ 26 int z = (1<<i)+(1<<j); 27 if(j+(j-i) < N) z |= (1<<2*j-i); 28 if(f[k^z] > f[k]+1){ 29 for(int fr=0;fr<des[k].size();fr++) 30 des[k^z].push_back(des[k][fr]); 31 des[k^z].push_back((node){i,j,2*j-i}); 32 f[k^z] = f[k]+1; 33 q.push(k^z); 34 } 35 } 36 } 37 } 38 } 39 40 node opt[maxn]; 41 int num; 42 43 node lst[maxn]; 44 45 void Remain(){ 46 queue<int> q; 47 memset(f,0x3f,sizeof(f)); 48 //for(int i=0;i<64;i++) des[i].clear(); 49 f[0] = 0;q.push(0); 50 int N = min(n,12); 51 while(!q.empty()){ 52 int k = q.front();q.pop(); 53 for(int i=0;i<N;i++){ 54 for(int j=i+1;j<N;j++){ 55 if(j+(j-i) >= N) break; 56 int z = (1<<i)+(1<<j)+(1<<2*j-i); 57 if(f[k^z] > f[k]+1){ 58 f[k^z] = f[k]+1; 59 lst[k^z] = (node){i,j,2*j-i}; 60 q.push(k^z); 61 } 62 } 63 } 64 } 65 int z = 0; 66 for(int i=n-N+1;i<=n;i++){z = (z<<1)+a[i];} 67 if(f[z] > 1e8){puts("NO");} 68 else{ 69 puts("YES"); 70 printf("%d ",num+f[z]); 71 for(int i=1;i<=num;i++){ 72 printf("%d %d %d ",opt[i].x,opt[i].y,opt[i].z); 73 } 74 while(z){ 75 printf("%d %d %d ",n-lst[z].z,n-lst[z].y,n-lst[z].x); 76 int pp = z; 77 z ^= (1<<lst[pp].x); z ^= (1<<lst[pp].y); z^= (1<<lst[pp].z); 78 } 79 } 80 } 81 82 void work(){ 83 for(int i=1;i<=n;i+=6){ 84 if(i+12 > n) break; 85 int z = (a[i+5]<<5)+(a[i+4]<<4)+(a[i+3]<<3)+(a[i+2]<<2)+(a[i+1]<<1)+a[i]; 86 for(int j=0;j<des[z].size();j++){ 87 opt[++num] = des[z][j]; 88 opt[num].x += i; opt[num].y += i; opt[num].z += i; 89 a[opt[num].x] ^= 1; a[opt[num].y] ^= 1; a[opt[num].z] ^= 1; 90 } 91 } 92 Remain(); 93 } 94 95 int main(){ 96 scanf("%d",&n); 97 for(int i=1;i<=n;i++) scanf("%d",&a[i]); 98 init(); 99 work(); 100 return 0; 101 }
以上是关于Codeforces1071C Triple Flips 构造Four Russians的主要内容,如果未能解决你的问题,请参考以下文章
Codeforces Round #784 (Div. 4)