1. 程式人生 > >bzoj4870: [Shoi2017]組合數問題(DP+矩陣乘法優化)

bzoj4870: [Shoi2017]組合數問題(DP+矩陣乘法優化)

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>
#define
ll 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]); }
View Code

bzoj4870: [Shoi2017]組合數問題(DP+矩陣乘法優化)