题解:
解题思路,发现式子的意义。
从nk个物品中选出%k为r个物品的方案数
然后DP
然后用矩阵快速幂加速
注意k==0的情况!!!
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn=60;
typedef long long Lint;
int mm;
int n,m,r;
struct Mat{
Lint arr[maxn][maxn];
Mat(){
memset(arr,0,sizeof(arr));
}
void Clea(){
memset(arr,0,sizeof(arr));
}
void MakeE(){
memset(arr,0,sizeof(arr));
for(int i=0;i<m;++i)arr[i][i]=1;
}
}Mx,My,Mz,Ma,Mret;
void Mul(){
Mz.Clea();
for(int i=0;i<m;++i){
for(int j=0;j<m;++j){
for(int k=0;k<m;++k){
Mz.arr[i][j]=(Mz.arr[i][j]+Mx.arr[i][k]*My.arr[k][j])%mm;
}
}
}
}
void Ksm(Lint p){
Mret.MakeE();
for(;p;p>>=1){
if(p&1){
Mx=Ma;My=Mret;Mul();Mret=Mz;
}
Mx=Ma;My=Ma;Mul();Ma=Mz;
}
}
int main(){
scanf("%d%d%d%d",&n,&mm,&m,&r);
for(int i=0;i<m;++i){
Ma.arr[i][(i-1+m)%m]++;
Ma.arr[i][i]++;
}
Ksm(1LL*n*m-1);
printf("%lld\n",(Mret.arr[r][0]+Mret.arr[r][1%m])%mm);
return 0;
}