1. 程式人生 > >Codeforces Round #341 (Div. 2) E - Wet Shark and Blocks

Codeforces Round #341 (Div. 2) E - Wet Shark and Blocks

取出 splay names mem pri 思路 turn const gpo

題目大意:有m (m<=1e9) 個相同的塊,每個塊裏邊有n個數,每個數的範圍是1-9,從每個塊裏邊取出來一個數組成一個數,讓你求組成的方案中

被x取模後,值為k的方案數。(1<=k<x<=100)

思路:剛開始把m看成了1e5,寫了一發數位dp,果斷RE,然後我在考慮從當塊前狀態轉移到下一個塊狀態模數的改變都用的是一套規則,因為

每個塊裏面的數字都是一樣的,那麽我們就可以很開心地構造出一個x*x的矩陣進行快速冪啦。

技術分享圖片
#include<bits/stdc++.h>
#define read(x) scanf("%d",&x)
#define ll long long
using
namespace std; const int mod=1e9+7; const int N=105; int cnt[10],n,b,k,x; struct node { node(int _row=0,int _col=0) { memset(a,0,sizeof(a)); row=_row; col=_col; } int row,col; ll a[N][N]; }; node mul(node x,node y) { node ans; ans.row=x.row,ans.col=y.col;
for(int i=0;i<x.row;i++) for(int j=0;j<y.row;j++) for(int k=0;k<y.col;k++) ans.a[i][k]=(ans.a[i][k]+x.a[i][j]*y.a[j][k])%mod; return ans; } node quick_mul(node x,int n) { node ans; ans.row=x.row; ans.col=x.col; for(int i=0;i<ans.row;i++) ans.a[i][i]
=1; while(n) { if(n&1) ans=mul(ans,x); x=mul(x,x); n>>=1; } return ans; } int main() { read(n); read(b); read(k); read(x); for(int i=1;i<=n;i++) { int p; read(p); cnt[p]++; } node A(x,x); for(int i=0;i<x;i++) { for(int j=0;j<x;j++) { for(int u=1;u<=9;u++) { int nx=(j*10+u)%x; if(nx!=i) continue; A.a[i][j]+=cnt[u]; } } } A=quick_mul(A,b); printf("%lld\n",A.a[k][0]); return 0; }
View Code

Codeforces Round #341 (Div. 2) E - Wet Shark and Blocks