51Nod1824 染色游戏 【Lucas定理】【FMT】【位运算】
我的FMT是在VFleaKing的论文中学到的。51Nod的评测机好恶心。
题目分析:
题目很明显是要你求一个类似卷积的式子。但是我们可以注意到前面具有组合数,如果拆成阶乘会很大,在模意义下你无法判断奇偶性。另辟蹊径,可以采用Lucas定理分析。
观察组合数的奇偶性,就会发现$\binom{n}{k} % 2 == 0$的充要条件是在模$2$意义下不存在$\binom{0}{1}$。这意味着$\binom{0}{0} \binom{1}{1} \binom{1}{0}$都是可以接受的。换句话说$k$是$n$的子集。注意到原来的是基础的卷积形式,所以我们要做的是对a和b的子集卷积。
全程在模$2$意义下进行,不难想到用二进制压位。
代码:
1 #include<bits/stdc++.h> 2 using namespace std; 3 4 #define RI register int 5 6 const int maxn = (1<<20)+5; 7 8 int n,m,len; 9 int a[maxn],b[maxn]; 10 char buffer[20000000], *buf=buffer; 11 12 inline void in(int &x) { 13 while(*buf>'9' || *buf<'0') ++buf; 14 for(x=0;*buf>='0'&&*buf<='9'; ++buf) x=x*10+*buf-'0'; 15 } 16 17 inline void in1(int &x){ 18 while(*buf>'9' || *buf<'0') ++buf; 19 x = *buf-'0';++buf; 20 } 21 22 struct Bitset{ 23 unsigned long long data[1<<14]; 24 int PrintBit(int now){ 25 int tm = now>>6,im = now&63; 26 return (bool)(data[tm]&(1ll<<im)); 27 } 28 void reset(int start,int len){ 29 int tm = start>>6,im = start&63; 30 if(len >= 64){ 31 int ww = len>>6; 32 for(RI i=0;i<ww;++i)data[tm+ww+i] ^= data[tm+i]; 33 }else{ 34 long long forw = (((1ll<<len)-1)<<im); 35 forw = (forw&data[tm]); 36 forw <<= len; data[tm] ^= forw; 37 } 38 } 39 void SetBit(int now){ 40 int tm = now>>6,im = now&63; 41 data[tm] |= (1ll<<im); 42 } 43 }am[21],bm[21],cm[21]; 44 45 int cnt[maxn]; 46 int f1,f2; 47 48 void read(){ 49 in(n),in(m); 50 for(RI i=1;i<=n;++i) in1(a[i]); 51 for(RI i=1;i<=m;++i) in1(b[i]); 52 for(RI i=1;i<=n;++i) a[i] &= 1; 53 for(RI i=1;i<=m;++i) b[i] &= 1; 54 n = (n>m?n:m);m = 1;len = 0; 55 while(m <= n) m<<=1,len++; 56 a[0] = b[0] = 1; 57 } 58 59 void FMT(int place,int st){ 60 if(place == 0){ 61 for(RI i=1;i<m;i<<=1){ 62 int jg = m/(i<<1); 63 for(RI j=0;j<m;j+=(jg<<1)) 64 am[st].reset(j,jg); 65 } 66 }else{ 67 for(RI i=1;i<m;i<<=1){ 68 int jg = m/(i<<1); 69 for(RI j=0;j<m;j+=(jg<<1)) 70 bm[st].reset(j,jg); 71 } 72 } 73 } 74 75 void IFMT(int num){ 76 for(RI i=1;i<m;i<<=1){ 77 for(RI j=0;j<m;j+=(i<<1)) 78 cm[num].reset(j,i); 79 } 80 } 81 82 void work(){ 83 for(RI i=1;i<m;++i) { cnt[i] = cnt[i>>1]+(i&1); } 84 for(RI i=0;i<=n;++i) { 85 if(a[i]) am[cnt[i]].SetBit(i); 86 if(b[i]) bm[cnt[i]].SetBit(i); 87 } 88 for(RI i=0;i<=len;++i){ FMT(0,i); FMT(1,i); } 89 for(RI i=0;i<m;++i){ 90 f1 = 0,f2 = 0; 91 for(RI j=0;j<=len;++j){ 92 f1 += (am[j].PrintBit(i)<<j); 93 f2 += (bm[j].PrintBit(i)<<j); 94 } 95 int n1 = 0,n2 = 0; 96 for(RI j=0;j<=len;++j){ 97 n1 = n1+(f1&(1<<j)); 98 if(f2&(1<<j)) n2 = (n2<<1)+1; 99 else n2 <<=1; 100 if(cnt[n1&n2]&1) cm[j].SetBit(i); 101 } 102 } 103 for(RI i=0;i<=len;++i) IFMT(i); 104 long long ans = 0; 105 for(RI i=0;i<m;++i){ 106 ans += 1ll*cm[cnt[i]].PrintBit(i)*i*i; 107 } 108 printf("%lld",ans); 109 } 110 111 int main(){ 112 fread(buffer, 1, (sizeof buffer)-1, stdin); 113 read(); 114 work(); 115 return 0; 116 }