codeforces 621E Wet Shack and blocks dp+矩阵幂优化!

来源:互联网 发布:网络渠道销售授权书 编辑:程序博客网 时间:2024/05/01 03:01

点击打开链接

题意 每块有n个数字,选b次 求最后组成的数%x==k的方法数 
dp[i][j]:i位数字,余数为j,cnt[i] digit i出现次数 
dp[i][(j*10+r)%x]+=dp[i][j]*cnt[r]  
总共有b位数字 b<=1e9 空间和时间都不够! 线性递推 构造矩阵优化!!!
 
矩阵aij为添加一位数字后 余数由i变为j的方法数 矩阵A为x*x方阵  
定义矩阵c为A*A 则cij=sigma(aik*akj) cij显然为添加2位后,余数从i变到j的方法数 
则求出A^b后c[0][k]即为添加b位数字后余数为k的方法数 


#include <iostream>#include <algorithm>#include <cstdio>#include <cstring>#include <vector> using namespace std;typedef long long ll;typedef vector<int> vec;typedef vector<vec> mat;const int N=1e3+20;const ll mod=1e9+7;ll b;int n,k,x,cnt[N];mat mul(mat a,mat b){mat c(a.size(),vec(b[0].size()));for(int i=0;i<a.size();i++){for(int j=0;j<b[0].size();j++){c[i][j]=0;for(int k=0;k<b.size();k++){c[i][j]=(c[i][j]+(ll)a[i][k]*b[k][j])%mod;}}}return c;}mat Pow(mat A,ll b){mat c(A.size(),vec(A.size()));for(int i=0;i<x;i++)c[i][i]=1;while(b){if(b&1)c=mul(c,A);A=mul(A,A);b>>=1;}return c;}int main(){cin>>n>>b>>k>>x;mat A(x,vec(x));memset(cnt,0,sizeof(cnt));for(int i=0;i<n;i++){int x;cin>>x;cnt[x]++;}//构造初始矩阵A[i][j] 添加一位后余数由i变为j的方法数 for(int i=0;i<x;i++){A[i][i]=0;for(int j=1;j<10;j++){ A[i][(i*10+j)%x]=(cnt[j]+A[i][(i*10+j)%x])%mod;}}A=Pow(A,b);cout<<A[0][k]<<endl;return 0;}


0 0
原创粉丝点击