题解:P3706 [SDOI2017] 硬币游戏&P6125 [JSOI2009] 有趣的游戏
首先发现两道题是相同的,但是 P3706 的数据更大,P6125 的字符集更大,同时每种字符的概率不同,接下来我们按 P6125 的题面和 P3706 的数据来叙述。
考虑设 \(f_{i,j}\) 为 \(j\) 次随机后恰好以第 \(i\) 个串结束的概率,其对于每个串的生成函数为 \(F_i(x)\)。设 \(g_i\) 为 \(i\) 次随机后仍未结束的概率,其生成函数为 \(G(x)\)。发现这个东西很像 P4548 [CTSC2006] 歌唱王国,因而我们可以按类似的做法(题解:P4548 [CTSC2006] 歌唱王国)来做。
令 \(P_i(l,r)\) 表示取到第 \(i\) 个串的 \([l,r]\) 的概率,即 \(\prod\frac pq\),\(n\) 为串的数量,\(L\) 为每个串的长度,\(m\) 为字符集的大小,则对于每个串 \(i\) 都有:
即我们在一个未结束状态后拼一整个 \(s_i\) 后必定会结束,但也有可能提前结束,如果提前结束在第 \(j\) 个串,则 \(j\) 的后拼的部分(一个后缀,假设长度为 \(k\))必然和 \(i\) 的前缀相同,即 \(s_i[1,k]=s_j[l-k+1,l]\),于是我们在后面拼上只是 \(s_i[k+1,l]\),所以要乘上 \(P_i(k+1,l)\)。又因为 \(i\) 的答案就是 \(F_i(1)=\sum_{j=0}^\infty f_{i,j}\),所以我们带入 \(x=1\),有:
于是我们可以通过哈希或 AC 自动机 \(O(n^3)\) 地列出关于 \(F_i(1)\) 和 \(G(1)\) 这 \(n+1\) 个变量的 \(n\) 个方程,再加上 \(\sum_{i=1}^nF_i(1)=1\) (因为有无限次随机,必定会结束)这个方程,共 \(n+1\) 个方程,高斯消元即可。
但是对于 P6125 需要特判一下 \(p=0\) 的情况,将这种情况下的 \(\frac pq\) 设为一个 \(10^{-7}\) 之类的小数,否则高斯消元会消到 \(0\) 然后寄掉。而且可能所有的串都不可能被摇出来,此时 \(\sum_{i=1}^nF_i(1)=0\) 也需要特判一下,可以对不能被摇出来的串直接输出 \(0\)。
参考资料:题解 P3706 【[SDOI2017]硬币游戏】,题解 P6125【[JSOI2009]有趣的游戏】
Code of P6125(P3706简单改一下就行):
#include<iostream>
#include<cmath>
#define rep(i,l,r) for(int i=(l);i<=(r);i++)
#define per(i,l,r) for(int i=(l);i>=(r);i--)
using namespace std;
const int maxn=310,mod=1e9+7;
typedef long long ll;
typedef long double ld;
const ld eps=1e-9;
ld a[maxn][maxn],ap[maxn][maxn],ac[30];
bool az[maxn],as[30];
int bas;
ll pw[maxn],pre[maxn][maxn],suf[maxn][maxn];
char s[maxn];
inline void gause(int n){
rep(v1,1,n){
int p=v1;
rep(v2,v1+1,n)if(abs(a[v2][v1])>abs(a[p][v1]))p=v2;
rep(v2,1,n+1)swap(a[v1][v2],a[p][v2]);
ld t=a[v1][v1];
rep(v2,1,n+1)a[v1][v2]/=t;
rep(v2,1,n)if(v2!=v1){
t=a[v2][v1];
rep(v3,1,n+1)a[v2][v3]-=t*a[v1][v3];
}
}
}
int main(){
// freopen("P6125_5.in","r",stdin);
int in,il,im;
cin>>in>>il>>im;
bas=im+1;
rep(v1,1,im){
int ip,iq;
scanf("%d %d",&ip,&iq);
if(ip)ac[v1-1]=ld(ip)/iq;
else ac[v1-1]=0.0000001,as[v1-1]=true;
}
pw[0]=1;
rep(v1,1,il)pw[v1]=pw[v1-1]*bas%mod;
rep(v1,1,in){
scanf("%s",s+1);
ap[v1][0]=1;
rep(v2,1,il)ap[v1][v2]=ap[v1][v2-1]*ac[s[v2]-'A'],az[v1]|=as[s[v2]-'A'];
rep(v2,1,il)pre[v1][v2]=(pre[v1][v2-1]*bas+s[v2]-'A'+1)%mod;
per(v2,il,1)suf[v1][v2]=((s[v2]-'A'+1)*pw[il-v2]+suf[v1][v2+1])%mod;
}
rep(v1,1,in){
rep(v2,1,in)rep(v3,1,il){
a[v1][v2]+=(pre[v1][v3]==suf[v2][il-v3+1])/ap[v1][v3];
}
a[v1][in+1]=-1;
}
rep(v1,1,in)a[in+1][v1]=1;
a[in+1][in+2]=1;
gause(in+1);
rep(v1,1,in)printf("%.2LF\n",az[v1]?0:a[v1][in+2]);
return 0;
}

浙公网安备 33010602011771号