【bitset 技巧 分块】bzoj5087: polycomp
神仙zq發(fā)現(xiàn)了${n^2\sqrt n}\over 32$做法
Description
你有三個(gè)系數(shù)為0,1的多項(xiàng)式f(x),g(x),h(x) 求f(g(x)) mod h(x) 為方便起見(jiàn),將答案多項(xiàng)式所有系數(shù)對(duì)2取模輸出即可 如果f(x)=Sigma(Ak * Xk) 則f(g(x))=Sigma(Ak(g(x))KInput
一共三行,每行一個(gè)多項(xiàng)式,分別為f,g,h 對(duì)于一個(gè)多項(xiàng)式描述為n P0,P1...Pn其中Pi為0或1 多項(xiàng)式P(x)=P0+P1*x+....+Pn*xn 記n表示多項(xiàng)式最高項(xiàng)的次數(shù),n<=4000Output
用同樣的格式輸出答案多項(xiàng)式 如果答案為0,輸出0 0題目分析
陳老師神題x1
觀察到這里多項(xiàng)式的所有操作都是在系數(shù)$\mod 2$的意義下的,因此可以用bitset來(lái)加速多項(xiàng)式的一些操作。例如$O(n^2)$實(shí)現(xiàn)多項(xiàng)式取模。
1 void mod(poly &a, int pos) 2 { 3 for (int i=pos; i>=p; i--) 4 if (a[i]) a ^= c<<(i-p), a[i] = 0; //我第一次居然把標(biāo)紅地方給忘了 5 }但是如同很多bitset的技巧題一樣,非常重要的一點(diǎn)是bitset每次整體操作的復(fù)雜度是??$O(size)$? 的。
這意味著$Poly\, +:O(n), \, Poly\, *:O(n^2)$
接下去我們從暴力開(kāi)始談起。
暴力做法 $O({{n^3}\over 32})$
第一個(gè)需要解決的問(wèn)題是:$f(g(x))$。那么我們只需要對(duì)$g(x)$求$k$次冪(也即最暴力地k次自乘),再將這些結(jié)果相加得到多項(xiàng)式$f(g(x))$。至于取模的過(guò)程,則可以在每次multiply的時(shí)候順帶模干凈,這樣最終相加得到的結(jié)果就是在模多項(xiàng)式意義下的答案。
1 void mod(poly &a, int pos) //pos是a的度數(shù) 2 { 3 for (int i=pos; i>=p; i--) 4 if (a[i]) a ^= c<<(i-p), a[i] = 0; 5 } 6 void mult(poly a, poly b, poly &ret) //ret=a*b 7 { 8 ret.reset(); 9 for (int i=0; i<=p; i++) 10 if (a[i]) ret ^= b<<i; //這里就是模擬n^2多項(xiàng)式乘法的過(guò)程 11 mod(ret, p<<1); 12 }總的代碼:
1 #include<bits/stdc++.h> 2 const int maxn = 8035; 3 typedef std::bitset<maxn> poly; 4 5 int n,m,p; 6 poly a,b,c,tmp,cnt; 7 8 void input(poly &a, int &n) 9 { 10 scanf("%d",&n); 11 for (int i=0, x; i<=n; i++) 12 { 13 scanf("%d",&x); 14 if (x) a.set(i); 15 } 16 } 17 void mod(poly &a, int pos) 18 { 19 for (int i=pos; i>=p; i--) 20 if (a[i]) a ^= c<<(i-p), a[i] = 0; 21 } 22 void mult(poly a, poly b, poly &ret) 23 { 24 ret.reset(); 25 for (int i=0; i<=p; i++) 26 if (a[i]) ret ^= b<<i; 27 mod(ret, p<<1); 28 } 29 int main() 30 { 31 input(a, n), input(b, m), input(c, p); 32 tmp[0] = 1, mod(b, m); 33 for (int i=0; i<=n; i++) 34 { 35 if (a[i]) cnt ^= tmp; 36 mult(tmp, b, tmp); //復(fù)雜度n^3在這里 37 } 38 while (p>=0&&!cnt[p]) --p; 39 if (p==-1) puts("0 0"); 40 else{ 41 printf("%d",p); 42 for (int i=0; i<=p; i++) 43 printf(" %d",cnt[i]?1:0); 44 } 45 return 0; 46 }對(duì)系數(shù)按10位分塊 $O({{n^3}\over 320})$
參見(jiàn)法老博客:[BITSET 分塊] BZOJ5087. polycomp
注:md[t]并不一定要等于0.這里的取模多項(xiàng)式最高位對(duì)計(jì)算無(wú)影響。
容易發(fā)現(xiàn)這種做法的復(fù)雜度的階仍然是$n^3$.
對(duì)$i=a\sqrt k+b$分塊 $O({{n^2\sqrt n}\over 32})$
233
轉(zhuǎn)載于:https://www.cnblogs.com/antiquality/p/10507033.html
總結(jié)
以上是生活随笔為你收集整理的【bitset 技巧 分块】bzoj5087: polycomp的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 邮储银行信用卡账单分期手续费怎么计算?这
- 下一篇: 【AtCoder】ARC078