1. 程式人生 > >51Nod1824 染色遊戲 【Lucas定理】【FMT】【位運算】

51Nod1824 染色遊戲 【Lucas定理】【FMT】【位運算】

turn art 位運算 sizeof data color define stdin 無法

我的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 }

51Nod1824 染色遊戲 【Lucas定理】【FMT】【位運算】