首页 > 代码库 > hdu6062多校题 构造

hdu6062多校题 构造

听说标算的点数是2^(n+1)级别的,也不知道我是不是比标算优一点?

(话说这种题一眼看过去怎么跟题答一样)

然而并不是题答,没法手玩,来考虑一下一般解法:

考虑一个规模较小的问题:最后一位一定是0

不难发现变成了条件完全相同的一个子问题

再把最后一位加上

那么总共2^(n-1)个答案中的一部分会翻车,

若把会翻车的部分标记为1,不会翻车的标记为0,又得到一个完全相同的子问题(规模与上一个子问题一样)

那么原问题就可以表示为

(这一位的输入,两个子问题)进行一次操作

没了

考虑复杂度f(x)=2f(x-1)+O(2^x),f(x)=2^x,轻松过

点数应该也差不多是2^n?

 1 #include <bits/stdc++.h>
 2 #define I n+2
 3 #define O n+3
 4 using namespace std;
 5 int n,N,E,sum;
 6 int a[20000],b[20000],c[20000];
 7 bool rule[20000],fir[20000];
 8 void addedge(int x,int y,int z)
 9 {
10     a[++E]=x;b[E]=y;c[E]=z;
11 }
12 void work(int st,int en,int len,int pos)
13 {
14     if(len==1)
15     {
16         if((rule[st]&1)&&(rule[en]&1)) addedge(O,n,pos),fir[pos]=1;
17         else
18         if(rule[st]&1) addedge(I,n,pos),fir[pos]=1;
19         else
20         if(rule[en]&1) addedge(I,n,pos),fir[pos]=0;
21         else
22         addedge(O,n,pos),fir[pos]=0;
23         return;
24     }
25     int mid=st+en>>1;
26     work(st,mid,len-1,pos);
27     for(int i=0;i<=mid-st;i++)
28         rule[mid+1+i]^=rule[st+i];
29     int POS=++N;
30     work(mid+1,en,len-1,POS);
31     addedge(POS,n-len+1,pos);
32     for(int i=0;i<=mid-st;i++)
33         rule[mid+1+i]^=rule[st+i];
34 }
35 int main()
36 {
37     while(~scanf("%d",&n))
38     {
39         N=n+3;E=0;
40         fir[I]=1;fir[O]=0;
41         for(int i=1;i<=1<<n;i++)
42         {
43             char ch;
44             for(ch=getchar();!isdigit(ch);ch=getchar());
45             for(sum=0;isdigit(ch);ch=getchar())
46                 sum=sum*2+ch-0;
47             scanf("%d",&rule[sum]);
48         }
49         work(0,(1<<n)-1,n,n+1);
50         printf("%d\n",fir[n+1]);
51         printf("%d\n",N-n-1);
52         for(int i=n+2;i<=N;i++)
53             printf("%d\n",fir[i]);
54         printf("%d\n",E);
55         for(int i=1;i<=E;i++)
56             printf("%d %d %d\n",a[i],b[i],c[i]);
57     }
58     return 0;
59 } 

 

hdu6062多校题 构造