[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)$,可以通过

 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 } 
View Code

 

posted @ 2021-07-16 16:08  PYWBKTDA  阅读(46)  评论(0编辑  收藏  举报