[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)

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

 

posted @ 2021-03-28 13:13  PYWBKTDA  阅读(106)  评论(0编辑  收藏  举报