# 「HNOI 2019」白兔之舞

LOJ #3058

Luogu P5293

### 题解

$$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}

$(sw^j+1)^L$这个矩阵我们只需要关注一个位置上的值

### 代码

#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;
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:;
}
}
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;
}