LG P4548 [CTSC2006]歌唱王国(概率生成函数+KMP求border)

105 篇文章 0 订阅
92 篇文章 0 订阅

题目

F ( x ) = ∑ i = 0 ∞ P ( 长 度 为 i 时 结 束 ) x i F(x)=\sum_{i=0}^{\infty} P(长度为i时结束)x^i F(x)=i=0P(i)xi
G ( x ) = ∑ i = 0 ∞ P ( 长 度 为 i 时 未 结 束 ) x i G(x)=\sum_{i=0}^{\infty} P(长度为i时未结束)x^i G(x)=i=0Pixi
∵ P ( 长 度 为 i 时 结 束 ) + P ( 长 度 为 i 时 未 结 束 ) = P ( 长 度 为 i − 1 时 未 结 束 ) \because P(长度为i时结束) +P(长度为i时未结束)=P(长度为i-1时未结束) P(i)+P(i)=P(i1)
∴ F ( x ) + G ( x ) = G ( x ) x + 1 \therefore F(x)+G(x) = G(x)x + 1 F(x)+G(x)=G(x)x+1
∴ F ′ ( x ) + G ′ ( x ) = G ( x ) x + G ( x ) \therefore F'(x)+G'(x)=G(x)x+G(x) F(x)+G(x)=G(x)x+G(x)
∴ F ′ ( 1 ) = G ( 1 ) \therefore F'(1) = G(1) F(1)=G(1)
∵ E = ∑ i = 0 ∞ i ∗ P ( 长 度 为 i 时 结 束 ) = ( x F ′ ( x ) ) ∣ x = 1 = F ′ ( 1 ) \because E = \sum_{i=0}^{\infty} i*P(长度为i时结束) = (xF'(x))|_{x=1} = F'(1) E=i=0iP(i)=(xF(x))x=1=F(1)
∴ E = G ( 1 ) \therefore E = G(1) E=G(1)

后面的过程比较抽象,开始说人话:
B o r d e r Border Border是指一个字符串中 s [ 1.... k ] = s [ n − k + 1..... n ] s[1....k] = s[n-k+1.....n] s[1....k]=s[nk+1.....n]也就是相等的前后缀。
s s s为名字的字符串。
一个没有结束的串 a a a,我们考虑如何让它变成一个结束的串。
显然我们要考虑一个结束的串 b b b是怎么从没有结束的串变来的。
我们发现 b b b的后面是一个 s s s,设去掉 s s s b b b变成了 a a a
那么 F ( x ) = G ( x ) ∗ 1 m ∣ s ∣ ∗ x ∣ s ∣ ? F(x) = G(x) * \frac 1{m ^ {|s|}} * x^{|s|}? F(x)=G(x)ms1xs?
发现可能在加入 s s s的一个前缀的时候就构成了 s s s
需要排除这种情况。
发现这种情况需要 s s s的前缀是 b o r d e r border border, a a a的后缀是 s s s去掉那个 b o r d e r border border后的串。
F ( x ) = G ( x ) ∗ 1 m ∣ s ∣ ∗ x ∣ s ∣ − ∑ s [ 1... i ]   i s   a   b o r d e r F ( x ) ∗ ( x m ) ∣ s ∣ − i F(x) = G(x) * \frac 1{m ^ {|s|}} * x^{|s|} - \sum_{s[1...i] \ is \ a \ border}F(x) * \left({\frac {x}{m}}\right)^{|s|-i} F(x)=G(x)ms1xss[1...i] is a borderF(x)(mx)si
我们需要求 G ( 1 ) G(1) G(1)就令 x = 1 x=1 x=1,又因为 F ( 1 ) = 1 F(1) = 1 F(1)=1
G ( 1 ) = m ∣ s ∣ + ∑ s [ 1... i ]   i s   a   b o r d e r m i G(1) = m^{|s|}+ \sum_{s[1...i] \ is \ a \ border}m^{i} G(1)=ms+s[1...i] is a bordermi
如果我们把原串也看作一个 b o r d e r border border
就是
E = G ( 1 ) = ∑ s [ 1... i ]   i s   a   b o r d e r m i E = G(1) = \sum_{s[1...i] \ is \ a \ border}m^{i} E=G(1)=s[1...i] is a bordermi
然后KMP求 b o r d e r border border就行,注意这个KMP和一般的不一样

AC Code:

#include<bits/stdc++.h>
#define maxn 100005
#define mod 10000
using namespace std;

int n,t,pw[maxn],a[maxn],nxt[maxn];

int main(){
	scanf("%d%d",&n,&t);
	pw[0] = 1;
	for(int i=1;i<=100000;i++) pw[i] = pw[i-1] * 1ll * n % mod;
	for(int m;t--;){
		scanf("%d",&m);
		for(int i=1;i<=m;i++)
			scanf("%d",&a[i]);
		nxt[0] = -1;
		for(int j=0,k=1;k<=m;)
			if(j==0 || a[k] == a[j]) nxt[k++] = j++;
			else j = nxt[j-1]+1;
		int ans = 0;
		for(int i=m;i;i=nxt[i])
			ans = (ans + pw[i]) % mod;
		printf("%04d\n",ans);
	}
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值