题目链接:
神仙思维题。
直接推式子是找不到什么性质的,我们来考虑一下这个式子的意义:
在(nk)个物品中,选(x(xmod{k}equiv r))个物品的方案数
那么可以DP:设(f[i][j])表示前(i)个物品,选(x(xmod{k}equiv j))个物品的方案数
则有:(f[i][j]=f[i-1][(j-1)mod{k}]+f[i-1][j])
那么就可以矩阵乘法优化了。
时间复杂度 (O(k^2log n))
注意特判(k=1)的情况
代码:
#include <cstdio>
#include <cstring>
#define rint register int
typedef long long ll;
int n,p,k,r;
struct Matrix
{
int n,m,a[55][55];
inline Matrix(int ns,int ms){n=ns,m=ms;memset(a,0,sizeof a);}
inline Matrix operator*(const Matrix &o)const
{
Matrix Res(n,o.m);
for(rint i=0;i<n;++i)
for(rint k=0;k<m;++k)
for(rint j=0;j<o.m;++j)
Res.a[i][j]=(Res.a[i][j]+(ll)a[i][k]*o.a[k][j])%p;
return Res;
}
};
int main()
{
scanf("%d%d%d%d",&n,&p,&k,&r);
Matrix f(1,k),g(k,k);
f.a[0][0]=1;
for(rint i=0;i<k;++i)++g.a[i][i],++g.a[i][(i+1)%k];//不直接赋值,防止k=1特殊情况
for(ll b=(ll)n*k;b;b>>=1,g=g*g)if(b&1)f=f*g;
printf("%d
",f.a[0][r]);
return 0;
}