就是求
nk
个物品里面取 模
k
余
这个直接dp
fi,j
表示前
i
个 余
矩阵快速幂是
O(k3logn)
实际上这个转移满足结合律 直接在快速幂的时候转移就好了
另一种理解是 这个矩阵是循环矩阵 矩阵的记录和乘法都只要处理第一行就好了
复杂度是
O(k2logn)
代码比想象中短
#include<cstdio>
#include<cstdlib>
#include<algorithm>
using namespace std;
typedef long long ll;
int n,P,k,r;
int a[55],b[55],t[55];
inline void mul(int *a,int *b){
for (int i=0;i<k;i++) for (int j=0;j<k;j++) (t[(i+j)%k]+=(ll)a[i]*b[j]%P)%=P;
for (int i=0;i<k;i++) a[i]=t[i],t[i]=0;
}
int main(){
freopen("t.in","r",stdin);
freopen("t.out","w",stdout);
scanf("%d%d%d%d",&n,&P,&k,&r);
a[0]++; b[0]++; b[1%k]++;
for (ll y=(ll)n*k;y;y>>=1,mul(b,b))
if (y&1)
mul(a,b);
printf("%d\n",a[r]);
return 0;
}