题目地址: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;
}