洛谷 P3706

Posted None

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了洛谷 P3706相关的知识,希望对你有一定的参考价值。

听说是 PGF 板板题,但是不会 PGF,怎么办捏(

暴力做法显然是建出 AC 自动机但是高斯消元,但是状态数高达 \\(nm\\),有没有优化的余地呢?

注意到终止状态只有 \\(n\\) 个,AC 自动机上其他节点表示的状态其实都可以归结为“非终止状态”,因此我们考虑设 \\(n\\) 个变量 \\(x_1\\sim x_n\\) 表示最先出现字符串 \\(s_i\\) 的概率,和一个辅助变量 \\(x_n+1\\) 表示当前位于不合法状态的概率(当然如果将这个解释为“概率”其实有点牵强,因为我们设立这个变量并不是为了解出 \\(x_n+1\\) 这个没啥实际意义的东西,而是计算出 \\(x_1\\sim x_n\\) 之间的比例关系,然后根据 \\(\\sum x_i=1\\) 解出所有 \\(x_i\\),但是其实我也找不到更好的解释方式,只好将这个东西用”概率“来解释)

考虑如何建立这 \\(n+1\\) 个变量之间的方程,对于每个字符串 \\(i\\),我们考虑现在我们在不合法状态,然后以 \\(2^-m\\) 的概率恰好在后面添加了字符串 \\(s_i\\),那么这个概率应该用什么来衡量呢?你可能说是 \\(x_i\\),但是问题在于,不一定非得添加完全部 \\(m\\) 个字符才能第一次得到 \\(s_i\\),比方说 \\(s_i=101\\),然后现在字符串末尾刚好有个 \\(10\\),这样添加一个 \\(1\\) 以后就到了 \\(x_i\\) 的状态。换句话说,添加完 \\(m\\) 个字符以后恰好第一次出现 \\(s_i\\) 的概率 \\(x_i\\) 只是 \\(x_n+1·2^-m\\) 的一部分。为了覆盖所有的情况,我们考虑所有字符串 \\(s_j\\)(当然,\\(j\\) 也可以等于 \\(i\\)),如果 \\(s_i\\) 长度为 \\(k\\) 的前缀与 \\(s_j\\) 长度为 \\(k\\) 的后缀完全相等,说明有可能是从 \\(x_k\\) 的状态以 \\(2^-(m-k)\\) 的概率添加了 \\(s_i\\) 的后 \\(m-k\\) 的字符得到当前状态的,因此我们有

\\[2^-mx_n+1=\\sum\\limits_j=1^n\\sum\\limits_k=1^m[s_i[1...k]=s_j[m-k+1...m]]x_j·2^-(m-k) \\]

当然最后还有个 \\(\\sum x_i=1\\)。直接高斯消元即可。

有点卡精度,很不明白为什么不取模,有点复古。下头/ruo

const int MAXN=300;
const u64 BS=131;
const ld EPS=1e-10;
int n,m;char s[MAXN+5][MAXN+5];
u64 pw_hsh[MAXN+5],pre[MAXN+5][MAXN+5],suf[MAXN+5][MAXN+5];
ld a[MAXN+5][MAXN+5],pw2[MAXN+5],res[MAXN+5];
int main()
	scanf("%d%d",&n,&m);
	for(int i=(pw_hsh[0]=pw2[0]=1);i<=m;i++)pw_hsh[i]=pw_hsh[i-1]*BS,pw2[i]=pw2[i-1]*0.5;
	for(int i=1;i<=n;i++)scanf("%s",s[i]+1);
	for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++)pre[i][j]=pre[i][j-1]*BS+s[i][j];
		for(int j=m;j;j--)suf[i][j]=suf[i][j+1]+pw_hsh[m-j]*s[i][j];
	
	for(int i=1;i<=n;i++)
		a[i][n+1]=-pw2[m];
		for(int j=1;j<=n;j++)for(int k=1;k<=m;k++)
			if(suf[j][m-k+1]==pre[i][k])a[i][j]+=pw2[m-k];
	
	for(int i=1;i<=n;i++)a[n+1][i]=1;a[n+1][n+2]=1;
	for(int i=1;i<=n+1;i++)
		int t=i;
		for(int j=i+1;j<=n+1;j++)if(fabs(a[j][i]-a[t][i])>EPS)t=j;
		for(int j=i;j<=n+2;j++)swap(a[i][j],a[t][j]);
		for(int j=i+1;j<=n+2;j++)a[i][j]/=a[i][i];a[i][i]=1;
		for(int j=i+1;j<=n+1;j++)
			for(int k=i+1;k<=n+2;k++)a[j][k]-=a[j][i]*a[i][k];
			a[j][i]=0;
		
	
	for(int i=n+1;i;i--)
		res[i]=a[i][n+2];
		for(int j=i+1;j<=n+1;j++)res[i]-=res[j]*a[i][j];
	
	for(int i=1;i<=n;i++)printf("%.10Lf\\n",res[i]);
	return 0;

Codevs 1497 取余运算== 洛谷P 1226

时间限制: 1 s   空间限制: 128000 KB   题目等级 : 钻石 Diamond
 
题目描述 Description

输入b,p,k的值,编程计算bp mod k的值。其中的b,p,k*k为长整型数(2^31范围内)。

输入描述 Input Description

b p k 

输出描述 Output Description

输出b^p mod k=?

=左右没有空格

样例输入 Sample Input

2  10  9

样例输出 Sample Output

2^10 mod 9=7

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 using namespace std;
 5 long long b,p,k,ans=1,q,t;
 6 int main()
 7 {
 8     scanf("%d%d%d",&b,&p,&k);q=p;t=b;
 9     while(p>0)
10     {
11         if(p%2==1) ans=(ans*b)%k;
12         p/=2;
13         b=(b*b)%k;
14     }
15     cout<<t<<^<<q<<" mod "<<k<<=<<ans<<endl;
16     return 0;
17 }

思路:快速幂

以上是关于洛谷 P3706的主要内容,如果未能解决你的问题,请参考以下文章

洛谷 P1055 ISBN号码

洛谷题目怎么看答案

洛谷的u id是啥

洛谷 P1193 洛谷团队训练VS传统团队训练

洛谷可以用手机刷题吗

洛谷洛谷月赛4月月赛Round 1/2