1. 程式人生 > 實用技巧 >CF621E Wet Shark and Blocks(矩陣加速DP)

CF621E Wet Shark and Blocks(矩陣加速DP)

題意:

n位數,有b組,從每一組中選取一位數,依次組成一個b位數,計算有多少種選法可以滿足結果%x=k

題解:

推匯出轉移方程後用矩陣加速,這裡構造矩陣的思路學習一位巨佬的寫法,還是要多練練矩陣!

/*
 *author: zlc
 *zucc_acm_lab
 *just do it
 */
#include<bits/stdc++.h> 
using namespace std;
typedef long long ll;
const double pi=acos(-1.0);
const double eps=1e-6;
const int mod=1e9+7;
const int
inf=1e9; const int maxn=2e5+100; inline ll read () {ll x=0,f=1;char ch=getchar();while (ch<'0'||ch>'9') {if (ch=='-') f=-1;ch=getchar();}while (ch>='0'&&ch<='9') {x=x*10+ch-'0';ch=getchar();}return x*f;} ll qpow (ll a,ll b) {ll res=1;a%=mod; assert(b>=0); for(;b;b>>=1){if(b&1
)res=res*a%mod;a=a*a%mod;}return res;} ll n,x,k,b; struct matrix { ll m[105][105]; }ans,base; void init () { memset(ans.m,0,sizeof(ans.m)); memset(base.m,0,sizeof(base.m)); for (int i=0;i<x;i++) ans.m[i][i]=1; } matrix mul (matrix a,matrix b) { matrix wjm; memset(wjm.m,0,sizeof(wjm.m));
for (int i=0;i<x;i++) for (int j=0;j<x;j++) { wjm.m[i][j]=0; for (int k=0;k<x;k++) wjm.m[i][j]=(wjm.m[i][j]+a.m[i][k]*b.m[k][j]%mod)%mod; } return wjm; } void qpow (ll p) { while (p) { if (p&1) ans=mul(ans,base); base=mul(base,base); p>>=1; } } int cnt[maxn]; int main () { n=read(),b=read(),k=read(),x=read(); for (int i=0;i<n;i++) { ll tt; tt=read(); cnt[tt]++; } init(); for (int i=0;i<x;i++) for (int j=0;j<=9;j++) { base.m[i][(i*10+j)%x]=(base.m[i][(i*10+j)%x]+cnt[j])%mod;//dp[i][j]表示從餘數i到餘數j的方法數 } qpow(b); printf("%lld\n",ans.m[0][k]); }