本文参考:bztMinamoto和露迭月巨佬的博客
前置知识:对生成函数有一定了解,有概率期望的一定基础。
定义:一个生成函数F(x),第i位表示某某为i的概率。
例题:[CTSC2006]歌唱王国
题意:
给定一个长度为的序列
。然后每次掷一个平骰子(有m种值)并将其上的数字加入到初始为空的序列
的末尾,如果序列
中已经出现了给定序列
,即
是
的子串,则停止。
题解:
设为
时间停止的概率,
为
时间不停止的概率,
,
分别为它们的生成函数。
这其实是
考虑对这个式子做出变形,两边同时求导
对取
,
考虑求出
介绍一个东西:对于一个长度为
的序列
,若
,则称
是
的一个
定义=
是
将带入
用
或
求出即可。
代码:
#include<bits/stdc++.h>
using namespace std;
#define next Next
#define gc getchar
#define int long long
/*char buf[1<<21],*p1=buf,*p2=buf;
inline int gc(){return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++;}*/
inline int read()
{
int ret=0,f=0;char c=gc();
while(!isdigit(c)){if(c=='-')f=1;c=gc();}
while(isdigit(c)){ret=ret*10+c-48;c=gc();}
if(f)return -ret;return ret;
}
const int N=1e5+5,P=1e4;
inline int add(int x,int y){return x+y>=P?x+y-P:x+y;}
inline int mul(int x,int y){return 1ll*x*y%P;}
int n,p,res,pos,bin[N],nxt[N],a[N];
signed main()
{
p=read(),bin[0]=1;
for(int i=1;i<=100000;i++)bin[i]=mul(bin[i-1],p);
int T=read();
while(T--)
{
n=read();
for(int i=1;i<=n;i++)a[i]=read();
nxt[0]=nxt[1]=0;
for(int i=2,j=0;i<=n;i++)
{
while(j&&a[j+1]!=a[i])j=nxt[j];
j+=(a[j+1]==a[i]);
nxt[i]=j;
}
pos=n,res=0;
while(pos)
{
res=add(res,bin[pos]);
pos=nxt[pos];
}
printf("%04lld\n",res);
}
return 0;
} 例题:[CTSC2006]歌唱王国
代码:
#include<bits/stdc++.h>
using namespace std;
#define next Next
#define gc getchar
/*char buf[1<<21],*p1=buf,*p2=buf;
inline int gc(){return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++;}*/
inline int read()
{
int ret=0,f=0;char c=gc();
while(!isdigit(c)){if(c=='-')f=1;c=gc();}
while(isdigit(c)){ret=ret*10+c-48;c=gc();}
if(f)return -ret;return ret;
}
const int N=305;
const int P=1e9+7;
const double eps=1e-10;
double a[N][N],b[N];
char s[N];
int n,m,bin[N],h[N][N];
inline int Hash(int i,int l,int r){return ((h[i][r]-1ll*h[i][l-1]*bin[r-l+1])%P+P)%P;}
void Gauss(int n)
{
for(int i=1;i<=n;i++)
{
if(a[i][i]>-eps&&a[i][i]<eps)
{
for(int j=i+1;j<=n;j++)if(a[j][i]<-eps||a[j][i]>eps)
{
for(int k=i;k<=n+1;k++)swap(a[i][k],a[j][k]);
break;
}
}
double t=1.0/a[i][i];
for(int j=i;j<=n+1;j++)a[i][j]*=t;
for(int j=i+1;j<=n;j++)
{
t=a[j][i];
for(int k=i;k<=n+1;k++)a[j][k]-=a[i][k]*t;
}
}
for(int i=n-1;i;i--)
for(int j=i+1;j<=n;j++)a[i][n+1]-=a[j][n+1]*a[i][j];
}
int main()
{
n=read();m=read();
bin[0]=b[0]=1;
for(int i=1;i<=m;i++)bin[i]=1ll*bin[i-1]*2%P,b[i]=b[i-1]*2;
for(int i=1;i<=n;i++)
{
scanf("%s",s+1);
for(int j=1;j<=m;j++)h[i][j]=(1ll*h[i][j-1]*2+(s[j]=='H'))%P;
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
for(int k=1;k<=m;k++)(Hash(i,1,k)==Hash(j,m-k+1,m))?a[i][j]+=b[k]:0;
a[i][n+1]=-1;
}
for(int i=1;i<=n;i++)a[n+1][i]=1;
a[n+1][n+2]=1;
Gauss(n+1);
for(int i=1;i<=n;i++)printf("%.8lf\n",a[i][n+2]);
return 0;
} 
京公网安备 11010502036488号