[hdu6316]Odd shops
记$m=10$,即商品的种类
记$g(x)=1+\sum_{i=1}^{m}a_{i}x_{i}$,问题即求$f_{n}(x)=g^{n}(x)$非0项数(模2意义下)
注意到$f^{2}(x)\equiv f(x^{2})(mod\ 2)$,这是因为如果所选的项在两边不同,那么交换后即会抵消
令$F(n,A)$为$A(x)f_{n}(x)$非0项数,即有$\begin{cases}F(n+1,A)=F(n,A\cdot g)\\F(2n,A)=F(n,E)+F(n,O)\end{cases}$
(其中$E(x)$和$O(x)$满足$A(x)=E(x^{2})+xO(x^{2})$,即将$A(x)$按照奇偶次划分)
第一个式子显然成立,对于第二个式子,考虑有
$$
A(x)f_{2n}(x)=A(x)f_{n}^{2}(x)\equiv E(x^{2})f_{n}(x^{2})+xO(x^{2})f_{n}(x^{2})(mod\ 2)
$$
注意到$E(x^{2})f_{n}(x^{2})$和$xO(x^{2})f_{n}(x^{2})$两者没有重复项,因此直接将两者的非0项数相加即可,同时显然两者的非0项数等于$E(x)f_{n}(x)$和$O(x)f_{n}(x)$的非0项数,递归即可
对于$F(n,A)$,注意到$n$有$o(\log n)$种,$A$最高次数不超过10(归纳即可),在模2意义下只有$2^{m+1}$种,总状态数即为$o(2^{m+1}\log n)$,直接递归计算即可
另外,关于$A$的存储可以使用int来表示,那么两数(多项式)相乘复杂度为$o(m)$
总复杂度为$o(m2^{m+1}\log n)$,可以通过
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define mod 998244353 4 int n,x,g,sum[(1<<11)],f[40][(1<<11)]; 5 int mul(int x,int y){ 6 int ans=0; 7 for(int i=0;i<=10;i++) 8 if (x&(1<<i))ans^=(y<<i); 9 return ans; 10 } 11 int dfs(int n,int a,int s){ 12 if (f[s][a]>=0)return f[s][a]; 13 if (!n)return sum[a]; 14 int aa=a; 15 if (n&1)aa=mul(a,g); 16 int E=0,O=0; 17 for(int i=0;i<=20;i++) 18 if (aa&(1<<i)){ 19 if (i&1)O|=(1<<(i>>1)); 20 else E|=(1<<(i>>1)); 21 } 22 return f[s][a]=(dfs((n>>1),E,s+1)+dfs((n>>1),O,s+1))%mod; 23 } 24 int main(){ 25 for(int i=0;i<(1<<11);i++)sum[i]=sum[(i>>1)]+(i&1); 26 while (scanf("%d",&n)!=EOF){ 27 g=1; 28 for(int i=1;i<=10;i++){ 29 scanf("%d",&x); 30 if (x&1)g|=(1<<i); 31 } 32 memset(f,-1,sizeof(f)); 33 printf("%d\n",dfs(n,1,0)); 34 } 35 }