题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=5318
这道题当时并没有看。。。因为我们队弱的只能5小时切水orz。。。首先关于这个题,我们先把重复的数字去除掉,然后建立一个变形用的change矩阵记录变化方式。。。矩阵快速幂部分的内容只能多刷一些题目来学习
其实有点不想详细讲。。。然而还是写了,绝对不是因为傲娇什么的。。。
首先,我们定义当前以第 i 根锁链结尾的数量为mat_cont [ i ];可以得到一组数字mat_cont;
然后,因为每种绳子都是无限的,所以当前以第 i 根绳子结尾的时候所能连接的绳子是一样的。
根据矩阵相乘的公式,如果第 i 根后面能接第 j 根,那么只要把 change[ i ][ j ]变成1就可以了。
语文并没有学好所以如果有什么说的不清楚的地方请加油自行脑补。。。
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> using namespace std; int num[55]; const int mod=1000000007; struct mat { int x; int num[55][55]; mat operator*(mat x) { mat ans; for(int i=0;i<x.x;i++) { for(int j=0;j<x.x;j++) { int temp=0; for(int k=0;k<x.x;k++) { temp=(int)((temp+(long long)num[i][k]*x.num[k][j])%mod); } ans.num[i][j]=temp; } } ans.x=x.x; return ans; } }change; int mat_cont[2][55]; int mat_num[55]; void show(int n) { for(int i=0;i<n;i++) { for(int j=0;j<n;j++) { cout<<change.num[i][j]<<" "; } cout<<endl; } } bool judge(int a,int b) { int k=1,n=b; while(n) { n/=10; k*=10; } //cout<<k<<endl; k/=100; int t=100; while(1) { if(a%t==b/k) return true; if(a%t==a || b/k==b) break; k/=10; t*=10; } return false; } int main() { int T; scanf("%d",&T); while(T--) { int n,m; scanf("%d%d",&n,&m); for(int i=0;i<n;i++) scanf("%d",&num[i]); sort(num,num+n); memset(change.num,0,sizeof change.num); memset(mat_cont,0,sizeof mat_cont); int cont=0; for(int i=0;i<n;i++) { if(num[i]<10) continue; if(num[i]==num[i-1]) { //mat_cont[0][cont-1]++; continue; } mat_cont[0][cont]++; mat_num[cont++]=num[i]; } change.x=cont; for(int i=0;i<cont;i++) { for(int j=0;j<cont;j++) { if(judge(mat_num[i],mat_num[j])) change.num[j][i]++; } } // for(int i=0;i<cont;i++) cout<<" "<<mat_num[i]; // cout<<endl; //show(cont); // cout<<change.num[0][0]<<" "; // cout<<change.num[0][1]<<endl; // cout<<change.num[1][0]<<" "; // cout<<change.num[1][1]<<endl; int flag=1; m--; while(m) { if(m&1) { for(int i=0;i<cont;i++) { int temp=0; for(int j=0;j<cont;j++) { temp=(int)((temp+(long long)change.num[i][j]*mat_cont[1-flag][j])%mod); } mat_cont[flag][i]=temp; } flag=1-flag; } change=change*change; //show(cont); //cout<<endl; m>>=1; } int ans=0; for(int i=0;i<cont;i++) ans=(ans+mat_cont[1-flag][i])%mod; printf("%d\n",ans); } return 0; }