Loading

忘却录音

Link

(数学方法忒难)考虑n²dp,dp[i][j]:前i对修改j个使其回文的方案数(第一对是第一个和最后一个,以此类推)
状态转移很容易想 f表示第i对是否相同 相同f=1 不同f=0
dp[i][j] = dp[i-1][j] * (f?1:0) + dp[i-1][j-1] * (f?0:2) + dp[i-1][j-2] * (f?25:24)
如果n是奇数 那么还需考虑最中间的那个数

code

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

#define int long long
const int N = 3005;
const int mod = 1e9+7;

int n,k;
int dp[N][N];
char s[N];
signed main()
{
	ios::sync_with_stdio(false);

	cin>>n>>k;
	cin>>s+1;
	
	if(n==1)
	{
		if(k==1) cout<<25;
		else cout<<0;
		return 0;
	}
	if(s[1]==s[n]) dp[1][0]=1,dp[1][1]=0,dp[1][2]=25;
	else dp[1][0]=0,dp[1][1]=2,dp[1][2]=24;
	
	for(int i=2;i<=n/2;i++)
	{
		bool f=(s[i]==s[n-i+1]);
		for(int j=0;j<=i*2&&j<=k;j++)
		{
			dp[i][j]+=dp[i-1][j]*(f?1:0)%mod,dp[i][j]%=mod;
			if(j-1>=0) dp[i][j]+=dp[i-1][j-1]*(f?0:2)%mod,dp[i][j]%=mod;
			if(j-2>=0) dp[i][j]+=dp[i-1][j-2]*(f?25:24)%mod,dp[i][j]%=mod;
		}
	}
	int ans;
	if(n%2) ans = dp[n/2][k]+dp[n/2][k-1]*25%mod, ans%=mod;
	else ans = dp[n/2][k];
	cout<<ans;
}

posted @ 2021-03-16 20:44  金木换  阅读(58)  评论(0)    收藏  举报