题意:有一张顶点数为
数据范围与约定:
对于全部数据,
对于每组测试点,特殊限制如下:
- 测试点
: ; - 测试点
: , 的最大质因子为 ; - 测试点
: , 的最大质因子为 ; - 测试点
: ; - 测试点
: ; - 测试点
: 的最大质因子为 。
解析:一道很难的多项式题。
我们先考虑
其中
我们转化一下,可得:
其中出现了
单位根反演
一个比较冷门的算法,它的主要形式为:
证明分为两种情况:
-
若
,我们设 ,则: -
-
若
,根据等比数列求和公式,则: -
它的主要应用是对于一个数列
我们首先构造
证明如下:
同理,若我们要求:
我们把
再用上面的式子即可求得所有
了解单位根反演后,代入原式,得:
后面这个和式
发现
接下来是一个神仙化简操作,利用如下恒等式:
代回原式:
其实现在就依稀可以看出后面那个和式是一个卷积形式,由于模数不一定要用 MTT 处理。为了更清楚地判断后面那个式子是不是卷积,我们继续化简。设
我们把枚举
然后经典套路,设
这时候能很轻易地看出后面的和式即为卷积形式,由于
代码中将矩阵的横纵坐标都减去了 long double,包括常量
/*
* @Author: clorf
* @Date: 2021-01-31 09:58:26
* @Last Modified by: clorf
* @Last Modified time: 2021-01-31 09:58:26
*/
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<ctime>
#include<cctype>
#define INF 2e9
using namespace std;
const int maxn=140000;
const long double Pi=acos(-1.0);
const double eps=1e-7;
//1.数组开小
//2.没用long long/爆了类型存储范围
//3.写之前式子没推清楚
//4.变量写错(想当然typo/没想清楚含义)
//5.写之前没想清楚复杂度
//6.常量数字与long long连用时要加ll!!!
//7.考虑无解和多解的情况
//8.两个int连成爆long long的一定要加1ll!!!!
//9.先除后乘!!!!!!
template<class T>void read(T &x)
{
x=0;int f=0;char ch=getchar();
while(!isdigit(ch)){f|=(ch=='-');ch=getchar();}
while(isdigit(ch)){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
x=f?-x:x;
return;
}
int n,k,L,x,y,p;
int maxx=1,num,omega[maxn>>1];
inline int inc(int a,int b){return a+b>=p?a+b-p:a+b;}
namespace poly
{
int rev[maxn*3];
struct Cnum
{
long double x,y;
Cnum(long double p=0,long double q=0){x=p,y=q;}
Cnum conj(){return Cnum(x,-y);}
friend Cnum operator + (Cnum a,Cnum b){return Cnum(a.x+b.x,a.y+b.y);}
friend Cnum operator - (Cnum a,Cnum b){return Cnum(a.x-b.x,a.y-b.y);}
friend Cnum operator * (Cnum a,Cnum b){return Cnum(a.x*b.x-a.y*b.y,a.x*b.y+a.y*b.x);}
}a[maxn*3],b[maxn*3],c[maxn*3],d[maxn*3];
inline void ready(int len)
{
while(maxx<=len)
{
maxx<<=1;
num++;
}
for(int i=0;i<maxx;i++)
rev[i]=(rev[i>>1]>>1)|((i&1)<<(num-1));
}
inline void FFT(Cnum *a,int maxx,int type)
{
for(int i=0;i<maxx;i++)
if(i<rev[i])
swap(a[i],a[rev[i]]);
for(int mid=1;mid<maxx;mid<<=1)
{
Cnum w1(cos(Pi/mid),type*sin(Pi/mid));
for(int r=mid<<1,j=0;j<maxx;j+=r)
{
Cnum w(1,0);
for(int k=0;k<mid;k++,w=w*w1)
{
Cnum x=a[j|k];
Cnum y=a[j|k|mid]*w;
a[j|k]=x+y;
a[j|k|mid]=x-y;
}
}
}
if(!(~type))
for(int i=0;i<maxx;i++)
{
a[i].x/=maxx;
a[i].y/=maxx;
}
}
inline void MTT(int *f,int *g,int *h,int maxx,int p)
{
for(int i=0;i<maxx;i++)
{
a[i].x=f[i]>>15;
a[i].y=f[i]&32767;
c[i].x=g[i]>>15;
c[i].y=g[i]&32767;
}
FFT(a,maxx,1);
FFT(c,maxx,1);
for(int i=1;i<maxx;i++)
{
b[maxx-i]=a[i].conj();
d[maxx-i]=c[i].conj();
}
b[0]=a[0].conj();
d[0]=c[0].conj();
for(int i=0;i<maxx;i++)
{
Cnum A=(a[i]+b[i])*Cnum(0.5,0);
Cnum B=(a[i]-b[i])*Cnum(0,-0.5);
Cnum C=(c[i]+d[i])*Cnum(0.5,0);
Cnum D=(c[i]-d[i])*Cnum(0,-0.5);
a[i]=A*C+Cnum(0,1)*(A*D+B*C);
b[i]=B*D;
}
FFT(a,maxx,-1);
FFT(b,maxx,-1);
for(int i=0;i<maxx;i++)
{
int A=(long long)(a[i].x+0.5)%p;
int B=(long long)(a[i].y+0.5)%p;
int C=(long long)(b[i].x+0.5)%p;
h[i]=(1ll*A*(1<<30)%p+1ll*B*(1<<15)%p+C+p)%p;
}
}
}
int f[maxn*3],g[maxn*3],h[maxn*3];
struct matrix
{
int s[3][3];
matrix(){memset(s,0,sizeof(s));}
friend matrix operator + (matrix a,matrix b)
{
matrix c;
for(int i=0;i<3;i++)
for(int j=0;j<3;j++)
c.s[i][j]=inc(a.s[i][j],b.s[i][j]);
return c;
}
friend matrix operator * (matrix a,int b)
{
matrix c;
for(int i=0;i<3;i++)
for(int j=0;j<3;j++)
c.s[i][j]=1ll*a.s[i][j]*b%p;
return c;
}
friend matrix operator * (matrix a,matrix b)
{
matrix c;
for(int i=0;i<3;i++)
for(int j=0;j<3;j++)
for(int k=0;k<3;k++)
c.s[i][j]=inc(c.s[i][j],1ll*a.s[i][k]*b.s[k][j]%p);
return c;
}
}e,st,w;
inline int power(int a,int b,int p)
{
int ans=1;
for(;b;b>>=1)
{
if(b&1)
ans=1ll*ans*a%p;
a=1ll*a*a%p;
}
return ans;
}
inline matrix power(matrix a,int b)
{
matrix ans=e;
for(;b;b>>=1)
{
if(b&1)
ans=ans*a;
a=a*a;
}
return ans;
}
inline int getroot(int x)
{
static int fac[50],cnt=0;
int num=x-1;
for(int i=2;i<=x-1;i++)
{
if(num==1)
break;
if(!(num%i))
{
fac[++cnt]=i;
while(!(num%i))
num/=i;
}
}
for(int g=2;;g++)
{
bool flag=1;
for(int j=1;j<=cnt;j++)
if(power(g,(x-1)/fac[j],x)==1)
{
flag=0;
break;
}
if(flag)
return g;
}
}
int main()
{
scanf("%d%d%d%d%d%d",&n,&k,&L,&x,&y,&p);
x--,y--;
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
scanf("%d",&w.s[i][j]);
e.s[0][0]=e.s[1][1]=e.s[2][2]=1;
st.s[0][x]=1;
omega[0]=1;
int G=getroot(p);
omega[1]=power(G,(p-1)/k,p);
for(int i=2;i<k;i++)
omega[i]=1ll*omega[i-1]*omega[1]%p;
int len=(k<<1)-2;
for(int i=0;i<=len;i++)
g[i]=omega[(k-1ll*i*(i-1)/2%k)%k];
for(int i=0;i<k;i++)
f[k-1-i]=1ll*omega[1ll*i*(i-1)/2%k]*(st*power(w*omega[i]+e,L)).s[0][y]%p;
len+=(k-1);
poly::ready(len);
poly::MTT(f,g,h,maxx,p);
int invk=power(k,p-2,p);
for(int i=0;i<k;i++)
printf("%lld\n",1ll*h[k-1+i]*invk%p*omega[1ll*i*(i-1)/2%k]%p);
return 0;
}

