jzoj5996

我們可以枚舉每一個串的最短回文後綴,這樣一定不會算重。

雖然一個字符串可能會有多個回文後綴,但是答案只會在最短的後綴被計算

記f[i]表示長度為i回文串中,沒有長度>1的回文後綴的個數,將總個數減去不合法個數得到答案

我們可以枚舉一個最短回文後綴,記長度為i,則前面n-i任意選,即使產生新回文也行,長度都比i大,則方案是sn−i∗f[i](2&lt;=i&lt;=n)s^{n-i}*f[i](2&lt;=i&lt;=n)sn−i∗f[i](2<=i<=n)

考慮如何計算f[i]f[i]f[i],記x=(i/2)x=(i/2)x=(i/2),則共有sxs^xsx個回文串

我們發現字符串從x->n部分,字符串沒有受到限制,隨便選,再記j為最短回文後綴長度,則f[i]f[i]f[i]要減去f[j]∗s[x−j]f[j]*s[x-j]f[j]∗s[x−j]

有可能最短回文長度會>x,無法計算,但是這個擔心不必要,因為最短回文長度<=x,這個命題可以證明

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll f[10000010],g[10000010],n,s,m,r,c;
int main(){
	freopen("suffix.in","r",stdin);
	freopen("suffix.out","w",stdout);
	scanf("%lld%lld%lld",&n,&s,&m);
	g[0]=1;
	for(int i=1;i<=n;i++)
		g[i]=g[i-1]*s%m;
	r=g[n];
	for(int i=1;i<=n;i++){
		int d=ceil(i/2.0);
		if(i%2==1){
			c=(c*s)%m;
			c=(c+f[d])%m;
		}
		f[i]=(g[d]-c+m)%m;
	}
	for(int i=2;i<=n;i++)
		r=(r-f[i]*g[n-i]%m+m)%m;
	printf("%lld\n",r);
}
上一篇:Oracle GoldenGate 12c实时捕获SQL Server数据


下一篇:Spring Cloud Alibaba 的服务注册与发现