列表

详情


NC14349. 音乐转换

描述

当你本题没有想出标准算法时,请不要提交此题,更不要恶意卡评测机
John是一位热衷的音游爱好者。
一天,他正在玩音游,碰到了一个难题。他面前有一个初始旋律,游戏目标是要把这一段初始旋律变成目标旋律。但是,难点在于,John并不能随意的改变这一旋律,每一次改变之后的旋律必须在他的旋律库中(或者为目标旋律),更令人头疼的是,每一次操作都需要消耗一定的combo,我们假设从A旋律改变成B旋律,那么这一次操作所消耗的Combo数是A与B的最大子旋律长度(最大公共子序列)再加1。需要注意的是,初始旋律必须变成旋律库中的一个旋律或者直接变成目标旋律,而旋律库中的任意一个旋律可以变成旋律库中的另外一个旋律,或者直接变成目标旋律,也可以变成初始旋律。而目标旋律则不能再进行任何操作。
 
John想问问你,在不限操作次数的情况下,一共有多少种方案使得初始旋律变成目标旋律,且一共消耗的combo数恰好为T,当然这个答案太大了,你只需要将它对1,000,000,007取余数就可以了。
请注意,再本题中,所有的旋律你都可以视为一个字符串。 

输入描述

输入第一行有两个正整数,分别为n和T,其中n代表曲库中的旋律数,T代表John所希望消耗的Combo数。
第二行有一个字符串,代表初始旋律。
第三行有一个字符串,代表目标旋律。
接下来N行,每行有一个字符串,代表旋律库中的旋律。
1<=N<=25
1<=T<=10^9
任意出现的一个字符串长度<=25
任意两个字符串的最长公共子序列的长度<=5
输入的n+2的字符串两两不同,且均由小写字母组成。

输出描述

输出只有一个正整数,代表方案数对1,000,000,007的余数。

示例1

输入:

2 4
ab
ba
bb
aa

输出:

2

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++14(g++5.4) 解法, 执行用时: 1000ms, 内存消耗: 1588K, 提交时间: 2020-08-05 20:28:35

#include<bits/stdc++.h>
#pragma GCC optimize(3,"Ofast","inline")
#define Fox ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
using namespace std;
const int mod=1e9+7;
int n,x,t,dp[30][30]; 
struct mat{
	int a[200][200];
}m,u;
char s[30][30];
mat matmul(mat c,mat d){
	int h=n*6;
	mat tmp;
	for(int i=1;i<=h;i++)
		for(int j=1;j<=h;j++){
			tmp.a[i][j]=0;
			for(int k=1;k<=h;k++)
				tmp.a[i][j]=(tmp.a[i][j]+1LL*c.a[i][k]*d.a[k][j]%mod)%mod;
		}
	return tmp;		
}
void matpow(int b){
	for(int i=1;i<=6*n;i++)u.a[i][i]=1;
	while(b){
		if(b&1)u=matmul(u,m);
		m=matmul(m,m);
		b>>=1;
	}
	printf("%d",u.a[1][2]);
}
int solve(int a,int b){
	memset(dp,0,sizeof(dp));
	int ans=0;
	int lena=strlen(s[a]+1),lenb=strlen(s[b]+1);
	for(int i=1;i<=lena;i++)
		for(int j=1;j<=lenb;j++)
			if(s[a][i]==s[b][j])dp[i][j]=dp[i-1][j-1]+1;
			else dp[i][j]=max(dp[i-1][j],dp[i][j-1]);
	for(int i=1;i<=lena;i++)
		for(int j=1;j<=lenb;j++)
			ans=max(ans,dp[i][j]);
	return ans+1;
}
int main(){
	scanf("%d%d",&n,&t);n+=2;
	for(int i=1;i<=n;i++)scanf("%s",s[i]+1);
	for(int i=1;i<=n;i++){
		for(int j=1;j<=5;j++)m.a[i+j*n][i+n*(j-1)]=1;
		if(i==2)continue;
		for(int j=1;j<=n;j++){
			if(i==j)continue;
			x=solve(i,j);
		//	cout<<i<<" "<<j<<" "<<x<<"\n";
			m.a[i][j+n*(x-1)]=1;
		}
	}
	matpow(t);
	return 0;
}

上一题