[hdu7013]String Mod

枚举$a$​​​和$b$​​​​​出现的次数,问题即求
$$
A_{i,j}=\sum_{p=0}^{L}\sum_{q=0}^{L-p}[n\mid (p-i)][n\mid (q-j)]{L\choose p}{L-p\choose q}(k-2)^{L-(p+q)}
$$
考虑单位根反演,即$[n\mid i]=\frac{\sum_{k=0}^{n-1}\omega^{ik}}{n}$​​(其中$\omega=g^{\frac{P-1}{n}}$​,$g$​为$P$​​的原根),代入后也即
$$
\sum_{p=0}^{L}\sum_{q=0}^{L-p}\frac{\sum_{x=0}^{n-1}\omega^{(p-i)x}}{n}\frac{\sum_{y=0}^{n-1}\omega^{(q-j)y}}{n}{L\choose p}{L-p\choose q}(k-2)^{L-(p+q)}
$$

将其整理并调换枚举顺序,即
$$
\frac{1}{n^{2}}\sum_{x=0}^{n-1}\sum_{y=0}^{n-1}\frac{1}{\omega^{ix}}\frac{1}{\omega^{jy}}\sum_{p=0}{L\choose p}(\omega^{x})^{p}\sum_{q=0}^{L-p}{L-p\choose q}(k-2)^{(L-p)-q}
$$
根据二项式定理,即
$$
\frac{1}{n^{2}}\sum_{x=0}^{n-1}\sum_{y=0}^{n-1}\frac{1}{\omega^{ix}}\frac{1}{\omega^{jy}}(\omega^{x}+{\omega^{y}}+k-2)^{L}
$$
类似于生成函数,考虑构造矩阵,即
$$
\begin{cases}X_{i,j}=Y_{i,j}=\frac{1}{\omega^{ij}}\\V_{i,j}=\frac{1}{n^{2}}(\omega^{i}+\omega^{j}+k-2)^{L}\end{cases}
$$
($i$​​和$j$​​的范围都是$[0,n)$​​,即矩阵大小为$n\times n$​​​)

根据式子不难得到$A=XVY$​,矩阵乘法计算即可

(另外关于$P$​的原根$g$​,不难暴力得到$g=13$成立)

时间复杂度为$o(n^{2}\log L+n^{3})$​​(前者为快速幂)​,可以通过

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define N 505
 4 #define mod 1000000009
 5 #define ll long long
 6 int t,m,n,g,invg,ans,A[N][N],X[N][N],V[N][N],Y[N][N];
 7 ll L;
 8 int qpow(int n,ll m){
 9     int s=n,ans=1;
10     while (m){
11         if (m&1)ans=(ll)ans*s%mod;
12         s=(ll)s*s%mod;
13         m>>=1;
14     }
15     return ans;
16 }
17 int main(){
18     scanf("%d",&t);
19     while (t--){
20         scanf("%d%lld%d",&m,&L,&n);
21         g=qpow(13,(mod-1)/n);
22         invg=qpow(g,mod-2);
23         for(int i=0;i<n;i++)
24             for(int j=0;j<n;j++){
25                 A[i][j]=0;
26                 X[i][j]=Y[i][j]=qpow(invg,i*j);
27                 V[i][j]=(ll)qpow(n*n,mod-2)*qpow((qpow(g,i)+qpow(g,j)+m-2)%mod,L)%mod;
28             }
29         for(int i=0;i<n;i++)
30             for(int j=0;j<n;j++)
31                 for(int k=0;k<n;k++)A[i][j]=(A[i][j]+(ll)X[i][k]*V[k][j])%mod;
32         for(int i=0;i<n;i++)
33             for(int j=0;j<n;j++){
34                 ans=0;
35                 for(int k=0;k<n;k++)ans=(ans+(ll)A[i][k]*Y[k][j])%mod;
36                 printf("%d",ans);
37                 if (j!=n-1)printf(" ");
38                 else printf("\n");
39             }
40     }
41     return 0;
42 } 
View Code

 

posted @ 2021-08-05 20:14  PYWBKTDA  阅读(59)  评论(0编辑  收藏  举报