[luogu7468]愤怒的小N
定义$count(x)$为$x$二进制下1的个数,答案即$\sum_{0\le x<n,count(x)\equiv 1(mod\ 2)}f(x)$
考虑预处理出$S_{k,i,p}=\sum_{0\le x<2^{i},count(x)\equiv p(mod\ 2)}x^{k}$,可以对$x$最高位是否为1分类讨论,转移即
$$
S_{k,i,p}=S_{k,i-1,p}+\sum_{0\le x<2^{i-1},count(x)\not\equiv p(mod\ 2)}(x+2^{i-1})^{k}=S_{k,i-1,p}+\sum_{j=0}^{k}2^{(i-1)(k-j)}{k\choose j}S_{j,i-1,p\oplus 1}
$$
$k$的枚举范围即$o(k)$,$i$的枚举范围即$o(\log n)$,因此预处理复杂度为$o(k^{2}\log n)$
更进一步的,假设给定字符串为$n_{i}$(下标从0开始,且假设长度为$l$),枚举与其相同的前缀长度,答案即
$$
\sum_{0\le i<l,n_{i}=1}\sum_{0\le j<2^{l-i-1}-1,count(j)\not\equiv p(mod\ 2)}f(lst+j)
$$
(其中$p=\sum_{j=0}^{i-1}n_{j}$,$lst\equiv \sum_{j=0}^{i-1}n_{j}2^{l-j-1}$)
对后者展开并化简,即
$$
\sum_{0\le i<l,n_{i}=1}\sum_{t_{1}=0}^{k-1}a_{t_{1}}\sum_{t_{2}=0}^{t_{1}}{t_{1}\choose t_{2}}lst^{t1-t2}S_{t_{2},l-i-1,p\oplus 1}
$$
这里的计算复杂度也是$o(k^{2}\log n)$,两者的复杂度都无法通过
打表可以发现$S_{k,i,0}=S_{k,i,1}$在$k<i$时成立,具体证明如下——
考虑对$i$进行归纳,即在$i=i_{0}$时成立,来证明$i=i_{0}+1$也成立
首先$0\le k\le i_{0}$,再对$k$分类讨论:
1.若$k<i_{0}$,考虑转移式中的每一项都有$k<i=i_{0}$小,根据归纳即成立
2.若$k=i_{0}$,具体代入转移,唯一无法证明相同的两项恰为$S_{k,i_{0},p}$以及$S_{k,i,p\oplus 1}$,两者具有对称性,即也相等
综上,我们即得到此结论
对于预处理,可以强制$i\le j$,那么状态数为$o(k^{2})$,预处理复杂度即降为$o(k^{3})$
当$t_{2}<l-i-1$,显然此时$i$的范围是$o(k)$的,暴力计算复杂度也是$o(k^{3})$的
当$t_{2}\ge l-i-1$,考虑$S_{k,i,0}+S_{k,i,1}=\sum_{j=0}^{2^{i}-1}j^{k}$,即$S_{t_{2},l-i-1,p\oplus 1}=\frac{\sum_{j=0}^{2^{l-i-1}-1}j^{t_{2}}}{2}$
将之代入,并将$j$的枚举提到前面,即$\frac{\sum_{0\le i<l,n_{i}=1}\sum_{j=0}^{2^{l-i-1}-1}f(j)}{2}$,对后者通过$o(k^{3})$对$f(x)$的前缀和插值预处理处这个$k$次多项式,即可$o(k)$计算,那么总复杂度即$o(k^{3}+k\log n)$
但这样还是无法通过,考虑令$ans_{p}=\sum_{0\le x<n,count(x)\equiv p(mod\ 2)}f(x)$,所求的$ans_{1}$也可以看作是$\frac{(ans_{0}+ans_{1})-(ans_{0}-ans_{1})}{2}$,对前后两者分类讨论:
对于前者,实际意义即$\sum_{i=0}^{n-1}f(i)$,由于已经确定是$n-1$的前缀和,可以$o(k^{2})$插值计算
对于后者,用同样的方式计算,仅是将统计答案时变为$S_{t_{2},l-i-1,p\oplus 1}-S_{t_{2},l-i-1,p\oplus 0}$,这对于$t_{2}<l-i-1$只需要改变一下式子即可,对于$t_{2}\ge l-i-1$可以发现该式即为0,因此$o(k\log n)$的部分就被优化了
综上,这一做法的复杂度是$o(k^{3}+\log n)$,可以通过
(然而代码还是TLE了,应该只是常数问题QAQ)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define N 500005 4 #define K 505 5 #define mod 1000000007 6 int n,k,ans,a[K],mi[N],fac[K],inv[K],x[K],y[K],f[K][K][2]; 7 char s[N]; 8 int c(int n,int m){ 9 return 1LL*fac[n]*inv[m]%mod*inv[n-m]%mod; 10 } 11 int pow(int n,int m){ 12 int s=n,ans=1; 13 while (m){ 14 if (m&1)ans=1LL*ans*s%mod; 15 s=1LL*s*s%mod; 16 m>>=1; 17 } 18 return ans; 19 } 20 int get_f(int x){ 21 int s=1,ans=0; 22 for(int i=0;i<k;i++){ 23 ans=(ans+1LL*s*a[i])%mod; 24 s=1LL*s*x%mod; 25 } 26 return ans; 27 } 28 void dfs(int l,int lst,int p){ 29 if (l>=n)return; 30 if (s[l]=='0'){ 31 dfs(l+1,lst,p); 32 return; 33 } 34 dfs(l+1,(lst+mi[n-l-1])%mod,(p^1)); 35 if (n-l-1<k) 36 for(int i=0;i<k;i++){ 37 int s=1; 38 for(int j=i;j>=0;j--){ 39 ans=(ans+mod-1LL*a[i]*c(i,j)%mod*s%mod*(f[j][n-l-1][(p^1)]+mod-f[j][n-l-1][p])%mod)%mod; 40 s=1LL*s*lst%mod; 41 } 42 } 43 } 44 int main(){ 45 mi[0]=1; 46 for(int i=1;i<N;i++)mi[i]=2*mi[i-1]%mod; 47 fac[0]=inv[0]=inv[1]=1; 48 for(int i=1;i<K;i++)fac[i]=1LL*fac[i-1]*i%mod; 49 for(int i=2;i<K;i++)inv[i]=1LL*(mod-mod/i)*inv[mod%i]%mod; 50 for(int i=1;i<K;i++)inv[i]=1LL*inv[i-1]*inv[i]%mod; 51 scanf("%s%d",s,&k); 52 n=strlen(s); 53 for(int i=0;i<k;i++)scanf("%d",&a[i]); 54 int nn=mod-1; 55 for(int i=0;i<n;i++) 56 if (s[i]=='1')nn=(nn+mi[n-i-1])%mod; 57 for(int i=0;i<=k;i++){ 58 x[i]=i; 59 y[i]=get_f(i); 60 if (i)y[i]=(y[i]+y[i-1])%mod; 61 } 62 for(int i=0;i<=k;i++){ 63 int s=y[i]; 64 for(int j=0;j<=k;j++) 65 if (j!=i)s=1LL*s*(nn-x[j]+mod)%mod*pow((x[i]-x[j]+mod)%mod,mod-2)%mod; 66 ans=(ans+s)%mod; 67 } 68 f[0][0][0]=1; 69 for(int i=0;i<k;i++) 70 for(int j=1;j<k;j++){ 71 for(int p=0;p<2;p++){ 72 f[i][j][p]=f[i][j-1][p]; 73 for(int t=0;t<=i;t++)f[i][j][p]=(f[i][j][p]+1LL*c(i,t)*pow(2,(j-1)*(i-t))%mod*f[t][j-1][p^1])%mod; 74 } 75 //i<j则S[i][j][0]=S[i][j][1] 76 //if (S[i][j][0]!=S[i][j][1])printf("%d %d\n",i,j); 77 } 78 dfs(0,0,1); 79 ans=1LL*ans*(mod+1)/2%mod; 80 printf("%d",ans); 81 return 0; 82 }