列表

详情


NC21587. 回文子序列计数

描述

我们称正着读与反着读一样的串为回文串,比如abba与racecar都是回文串
我们称长度为奇数的回文为奇回文,中间的字符称为回文中心

有一个字符串S包含N个小写字母
令x[i]表示以i为回文中心的回文子序列的个数 (0 <= i <= N-1)
换句话说:保留第i个字符,X[i]表示有多少种字符的删除方案可以使得剩下的字符是一个以i为中心的回文串

 Y[i] = ((i+1) * X[i])%1000000007
 返回所有Y的xor之和
 
 所有字母都是小写字母

输入描述

输入一行包含一个字符串,字符串的长度(1 <= N <= 3000)

输出描述

输出一个整数

示例1

输入:

axbcba

输出:

31

示例2

输入:

eeeee

输出:

14

示例3

输入:

zyzyzzzzxzyz

输出:

221

示例4

输入:

aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa

输出:

1044407608

原站题解

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

C++(g++ 7.5.0) 解法, 执行用时: 38ms, 内存消耗: 572K, 提交时间: 2022-10-25 16:17:11

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=3e3+5;
const int mod=1e9+7;
ll X[N],dp[N];
char s[N];
int main(){
    scanf("%s",s+1);
    int len=strlen(s+1);
    X[1]=1;
    X[len]=1;
    for(int i=2;i<len;i++){
    	X[i]=1;
    	ll sum=0,cnt=0;
    	for(int j=len;j>i;j--){
    		cnt=dp[j];
    		if(s[j]==s[i-1]){
    			dp[j]=(dp[j]+sum+1)%mod;
		}
		sum=(sum+cnt)%mod;
		X[i]=(X[i]+dp[j])%mod;
	 }
    }
	ll ans=0;
	for(int i=1;i<=len;i++) ans=ans^(((i)*X[i])%mod);
	printf("%lld\n",ans);
	return 0;
}

C++14(g++5.4) 解法, 执行用时: 45ms, 内存消耗: 612K, 提交时间: 2019-09-19 14:59:56

#include<bits/stdc++.h>
using namespace std;
const int mod=1e9+7;
long long dp[3005],x[3005];
char s[3005];
int main(){
    cin>>s; int n=strlen(s);
    x[0]=x[n-1]=1;
    for(int i=1;i<n-1;i++){
        x[i]=1; int sum=0,cnt;
        for(int j=n-1;j>i;j--){
            cnt=dp[j];
            if(s[j]==s[i-1]) dp[j]=(dp[j]+sum+1)%mod;
            sum=(sum+cnt)%mod;
            x[i]=(x[i]+dp[j])%mod;
        }
    }
    long long ans=0;
    for(int i=0;i<n;i++) ans=ans^(((i+1)*x[i])%mod);
    cout<<ans<<endl;
    return 0;
}

C++11(clang++ 3.9) 解法, 执行用时: 45ms, 内存消耗: 628K, 提交时间: 2019-09-13 13:24:27

#include<bits/stdc++.h>
#define ll long long 
using namespace std;
const int mod=1000000007;
ll dp[3010],x[3010];
string s;
int main()
{
	cin>>s;
	int len=s.size();
	x[0]=1,x[len-1]=1;
	for(int i=1;i<len-1;i++)
	{
		x[i]=1;
		ll sum=0,ans=0;
		for(int j=len-1;j>i;j--)
		{	
		ans=dp[j];
		if(s[j]==s[i-1])
		dp[j]=(dp[j]+sum+1)%mod;
		sum=(sum+ans)%mod;
		x[i]=(x[i]+dp[j])%mod;
		} 
	}
	ll ans1=0;
	for(int i=0;i<len;i++) ans1=ans1^(((i+1)*x[i])%mod);
	cout<<ans1<<endl;
	return 0;
 } 

上一题