一道清真的數論題html
LOJ #3058ios
Luogu P5293git
考慮$ n=1$的時候怎麼作less
設$ s$爲轉移的方案數spa
設答案多項式爲$\sum\limits_{i=0}^L (sx)^i\binom{L}{i}=(sx+1)^L$code
答案至關於這個多項式模$ k$的各項係數的和htm
發現這和LJJ學二項式定理幾乎如出一轍blog
我上一題的題解ci
然而直接搞是$ k^2$的,沒法直接經過本題get
如下都用$ w$表示$ k$次單位根
設$ F_i$爲次數模$ k$爲$ i$的項的係數和
單位根反演一下獲得$F(i)=\sum\limits_{j=0}^{k-1}w^{-ij}(sw^j+1)^L$
組合數有個很是優美的性質
$$ij=\binom{i+j}{2}-\binom{i}{2}-\binom{j}{2}$$
推波式子
$$
\begin{aligned}
F(i)&=\sum_{j=0}^{k-1}w^{-ij}(sw^j+1)^L\\
&=\sum_{j=0}^{k-1}w^{\binom{i}{2}+\binom{j}{2}-\binom{i+j}{2}}(sw^j+1)^L\\
&=w^\binom{i}{2}\sum_{j=0}^{k-1}w^{-\binom{i+j}{2}}w^\binom{j}{2}(sw^j+1)^L\\
\end{aligned}
$$
發現這是一個差卷積的形式
扔一個$ MTT$上去就能拿那$ 40$分了
考慮$ n>1$的狀況
至關於把$ s$從一個數變成了矩陣,把$ 1$變成單位矩陣
$ (sw^j+1)^L$這個矩陣咱們只須要關注一個位置上的值
所以能夠乘出來而後取[x][y]這個位置上的數便可
這樣就能夠經過此題
複雜度:大常數單 $\log$
#include<ctime> #include<cmath> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #include<queue> #include<vector> #define rt register int #define ll long long using namespace std; inline ll read(){ ll x=0;char zf=1;char ch=getchar(); while(ch!='-'&&!isdigit(ch))ch=getchar(); if(ch=='-')zf=-1,ch=getchar(); while(isdigit(ch))x=x*10+ch-'0',ch=getchar();return x*zf; } void write(ll y){if(y<0)putchar('-'),y=-y;if(y>9)write(y/10);putchar(y%10+48);} void writeln(const ll y){write(y);putchar('\n');} int k,m,n,x,y,cnt,p,L; int w[65539],val[65539]; int f[65539],g[65539],F[65539]; int ksm(int x,int y=p-2){ int ans=1; for(;y;y>>=1,x=1ll*x*x%p)if(y&1)ans=1ll*ans*x%p; return ans; } struct mat{ ll a[3][3]; void print(){ for(rt i=0;i<n;i++)for(rt j=0;j<n;j++)cout<<a[i][j]<<" \n"[j==n-1]; } inline mat operator*(const mat s)const{ mat ret={0}; for(rt i=0;i<n;i++) for(rt k=0;k<n;k++) for(rt j=0;j<n;j++) (ret.a[i][j]+=a[i][k]*s.a[k][j]); for(rt i=0;i<n;i++)for(rt j=0;j<n;j++)ret.a[i][j]%=p; return ret; } mat operator*(const int s)const{ mat ret; for(rt i=0;i<n;i++) for(rt j=0;j<n;j++) ret.a[i][j]=a[i][j]*s%p; return ret; } mat operator+(const mat s)const{ mat ret;memset(ret.a,0,sizeof(ret.a)); for(rt i=0;i<n;i++) for(rt j=0;j<n;j++) ret.a[i][j]=(a[i][j]+s.a[i][j])%p; return ret; } }I,zy; mat ksm(mat x,int y){ mat ans=I; for(;y;y>>=1,x=x*x)if(y&1)ans=ans*x; return ans; } int V(int x){ return 1ll*x*(x-1)/2%k; } const double PI=acos(-1.0); struct cp{ double x,y; cp operator +(const cp &s)const{return {x+s.x,y+s.y};} cp operator -(const cp &s)const{return {x-s.x,y-s.y};} cp operator *(const cp &s)const{return {x*s.x-y*s.y,x*s.y+y*s.x};} }W[18][1<<17],A[270010],B[270010],C[270010],D[270010]; int R[270010]; void FFT(const int n,cp *A){ for(rt i=0;i<n;i++)if(i>R[i])swap(A[i],A[R[i]]); for(rt j=0;j<n;j+=2){ const cp x=A[j],y=A[j+1]; A[j]=x+y,A[j+1]=x-y; } for(rt i=2,s=1;i<n;i<<=1,s++) for(rt j=0;j<n;j+=i<<1) for(rt k=0;k<i;k+=2){ cp x=A[j+k],y=W[s][k]*A[i+j+k]; A[j+k]=x+y;A[i+j+k]=x-y; x=A[j+k+1],y=W[s][k+1]*A[i+j+k+1]; A[j+k+1]=x+y;A[i+j+k+1]=x-y; } } int yg(int n){ for(rt i=1;i<=n;i++){ for(rt j=2;j*j<=n;j++)if((n-1)%j==0) if(ksm(i,(n-1)/j)==1)goto end; return i;end:; } } void subtask(){ w[0]=1;w[1]=ksm(yg(p),(p-1)/k); for(rt i=2;i<k;i++)w[i]=1ll*w[i-1]*w[1]%p;mat s=zy; for(rt i=0;i<k;i++){ g[i]=ksm(s*w[i]+I,L).a[x-1][y-1]*w[V(i)]%p; } for(rt i=0;i<k+k;i++)f[i]=w[(k-V(i))%k]; for(rt i=0;i<k/2;i++)swap(g[i],g[k-i]); n=k+k-1;m=k; int lim=1;while(lim<=n+m)lim<<=1; for(rt i=0;(1<<i)<lim;i++){ W[i][0]={1,0}; W[i][1]={cos(PI/(1<<i)),sin(PI/(1<<i))}; for(rt j=2;j<1<<i;j++) if(j%32==0)W[i][j]={cos(PI*j/(1<<i)),sin(PI*j/(1<<i))}; else W[i][j]=W[i][j-1]*W[i][1]; } for(rt i=0;i<=n;i++){ A[i].x=f[i]>>15; A[i].y=f[i]&32767; } for(rt i=0;i<=m;i++){ B[i].x=g[i]>>15; B[i].y=g[i]&32767; } for(rt i=1;i<lim;i++)R[i]=(R[i>>1]>>1)|(i&1)*(lim>>1); FFT(lim,A);FFT(lim,B); for(rt i=0;i<lim;i++){ const int pl=(lim-1)&(lim-i); const cp ca={A[pl].x,-A[pl].y},cb={B[pl].x,-B[pl].y}; const cp a=(A[i]+ca)*(cp){0.5,0},b=(A[i]-ca)*(cp){0,-0.5}, c=(B[i]+cb)*(cp){0.5,0},d=(B[i]-cb)*(cp){0,-0.5}; C[pl]=a*c+a*d*(cp){0,1};D[pl]=b*c+b*d*(cp){0,1}; } FFT(lim,C);FFT(lim,D); for(rt i=k;i<k+k;i++){ const int vv=1ll*w[V(i-k)]*ksm(k,p-2)%p; ll a=C[i].x/lim+0.5,b=C[i].y/lim+0.5,c=D[i].x/lim+0.5,d=D[i].y/lim+0.5; a=((a%p)<<30)+(((b+c)%p)<<15)+d;a=(a%p+p)%p; writeln(1ll*a*vv%p); } exit(0); } int jc[100010],njc[100010],inv[100010],ff[100010][3],ans[100010]; int c(int x,int y){ return 1ll*jc[x]*njc[y]%p*njc[x-y]%p; } void bl(){ for(rt i=0;i<2;i++)jc[i]=njc[i]=inv[i]=1; for(rt i=2;i<=L;i++){ jc[i]=1ll*jc[i-1]*i%p; inv[i]=1ll*inv[p%i]*(p-p/i)%p; njc[i]=1ll*njc[i-1]*inv[i]%p; } ff[0][x-1]=1;if(x==y)ans[0]=1; for(rt i=1;i<=L;i++) for(rt j=0;j<n;j++){ for(rt k=0;k<n;k++) (ff[i][j]+=1ll*zy.a[k][j]*ff[i-1][k]%p)%=p; if(j==y-1)(ans[i%k]+=1ll*ff[i][j]*c(L,i)%p)%=p; } for(rt i=0;i<k;i++)writeln(ans[i]);exit(0); } int main(){ cin>>n>>k>>L>>x>>y>>p; for(rt i=0;i<n;i++) for(rt j=0;j<n;j++) cin>>zy.a[i][j]; if(L<=100000)bl(); for(rt i=0;i<n;i++)I.a[i][i]=1; subtask(); return 0; }