bzoj4870: [Shoi2017]組合數問題(DP+矩陣乘法優化)
阿新 • • 發佈:2017-10-04
mod ons int for getc 組合數 b- col str
為了1A我居然寫了個暴力對拍...
那個式子本質上是求nk個數裏選j個數,且j%k==r的方案數。
所以把組合數的遞推式寫出來f[i][j]=f[i-1][j]+f[i-1][(j-1+k)%k]...我們知道求組合數實際上是可以矩陣乘法優化的,只是沒必要,但是這個時候就用上了...
於是矩陣乘法優化,AC之~
#include<iostream> #include<cstring> #include<cstdlib> #include<cstdio> #include<algorithm> #defineView Codell long long #define MOD(x) ((x)>=p?(x)-p:(x)) using namespace std; const int maxn=310,inf=1e9; typedef ll mtx[60][60]; int n,p,K,r; mtx f,g; void read(int &k) { int f=1;k=0;char c=getchar(); while(c<‘0‘||c>‘9‘)c==‘-‘&&(f=-1),c=getchar(); while(c<=‘9‘&&c>=‘0‘)k=k*10+c-‘0‘,c=getchar(); k*=f; } void mul(mtx &a,mtx b) { mtx c;memset(c,0,sizeof(c)); for(int i=1;i<=K;i++) for(int j=1;j<=K;j++) for(int k=1;k<=K;k++) c[i][j]=(c[i][j]+a[i][k]*b[k][j])%p; memcpy(a,c,sizeof(c)); } void power(ll b) { for(;b;mul(f,f),b>>=1) if(b&1)mul(g,f); } int main() { read(n);read(p);read(K);read(r); for(int i=1;i<=K;i++)g[i][i]=1,f[i][i]=1; for(int i=1;i<=K;i++)f[i][(i-2+K)%K+1]++; power(1ll*n*K); printf("%lld\n",g[r+1][1]); }
bzoj4870: [Shoi2017]組合數問題(DP+矩陣乘法優化)