首页 > 其他分享 >P3706 「SDOI2017」硬币游戏 解题报告

P3706 「SDOI2017」硬币游戏 解题报告

时间:2024-02-27 17:46:08浏览次数:21  
标签:pre frac int 305 P3706 解题 frac1 SDOI2017 include

oj:https://gxyzoj.com/d/hzoj/p/P451

概率与期望+hash+高斯消元

声明一些东西,pre(S,l)表示串S的长度为l的前缀,lst(S,l)表示串S的长度为l的后缀

一. 对于所有串建立字典树,像「HNOI2013」游走 一样高斯消元,时间复杂度 \(O(n^3m^3)\) ,预计50/70pts

二. 正解:

  1. 显然,n项中,出现一个长度为n的串s的概率为 \(\frac{1}{2^n}\)

  2. 先从部分分入手,当n=2时,设两串A=101,B=110,有一个不含这两个串的串S,显然,在S后直接加上A,概率\(\frac{1}{8}\),游戏结束。

但有一些特殊情况:

(1)S的结尾是10,则再加上1则会出现A串,游戏结束,概率\(\frac{1}{2}\)

(2)S的结尾是1,则再加上10则会出现B串,游戏结束,概率\(\frac{1}{4}\)

(3)其余情况,第一个人获胜

故\(\frac1 8 S=\frac1 4A+\frac1 2B+A\)

同理,可得加上B的情况,得 \(\frac1 8 S=\frac1 4A+B\)

解得\(A=\frac2 3,B=\frac1 3\)

从中,可得到只有2个串的式子:

\[\frac{1}{2^m}S=\sum_{pre(A,i)=lst(A,i)}x_A\times \frac{1}{2^{m-i}}+\sum_{pre(A,i)=lst(B,i)}x_B\times \frac{1}{2^{m-i}} \]

按照如上方法,可列出关于B的式子

依题意得:\(x_A+x_B=1\),三个式子,三个未知数,可以高斯消元

  1. 推广2的式子,可以得到:

\[\frac{1}{2^m}S=\sum_{i=1}^n \sum_{pre(s_{now},l)=lst(s_i,l)}x_i\times \frac{1}{2^{m-l}} \]

高斯消元求解即可

警示后人:注意eps的大小,最好设成\(10^{-300}\),这题卡精度!!!

  1. 代码:
#include<cstdio>
#include<iostream>
#include<string>
#include<algorithm>
#include<cmath>
#define ull unsigned long long
using namespace std;
int n,m,q=2;
ull pre[305][305],p1[305];
string s[305];
double a[305][305],p[305],eps=1e-300;
void guass()
{
	for(int i=1;i<=n;i++)
	{
		for(int j=i;j<=n;j++)
		{
			if(fabs(a[i][i])<fabs(a[j][i]))
			{
				swap(a[i],a[j]);
			}
		}
		if(fabs(a[i][i])>eps)
		{
			for(int j=n+1;j>=i;j--)
			{
				a[i][j]/=a[i][i];
			}
			for(int j=i+1;j<=n;j++)
			{
				for(int k=n+1;k>=i;k--)
				{
					a[j][k]-=a[j][i]*a[i][k];
				}
			}
		}
	}
	for(int i=n-1;i>0;i--)
	{
		for(int j=i+1;j<=n;j++)
		{
			a[i][n+1]-=a[i][j]*a[j][n+1];
		}
	}
}
int main()
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++)
	{
		cin>>s[i];
		s[i]=" "+s[i];
		for(int j=1;j<=m;j++)
		{
			if(s[i][j]=='H') s[i][j]=0;
			else s[i][j]=1;
			pre[i][j]=pre[i][j-1]*q+s[i][j]; 
		}
	}
	p[0]=p1[0]=1;
	for(int i=1;i<=m;i++)
	{
		p1[i]=p1[i-1]*q;
		p[i]=p[i-1]*0.5;
	}
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=n;j++)
		{
			for(int l=1;l<=m;l++)
			{
				if(pre[i][l]==pre[j][m]-pre[j][m-l]*p1[l])
				{
		//			printf("%d %d %d\n",i,j,l);
					a[i][j]+=p[m-l];
				}
			}
		}
	}
	for(int i=1;i<=n;i++) a[i][n+1]=-p[m];
	for(int i=1;i<=n;i++) a[n+1][i]=1;
	a[n+1][n+2]=1;
	n++;
//	for(int i=1;i<=n+1;i++)
//	{
//		for(int j=1;j<=n+2;j++)
//		{
//			printf("%.10lf ",a[i][j]);
//		}
//		printf("\n");
//	}
	guass();
	for(int i=1;i<n;i++)
	{
		printf("%.10lf\n",a[i][n+1]);
	}
	return 0;
}

标签:pre,frac,int,305,P3706,解题,frac1,SDOI2017,include
From: https://www.cnblogs.com/wangsiqi2010916/p/18037377

相关文章

  • CF464E 解题报告
    首先这是一道最短路的题目,但是数据范围十分庞大,需要高精度。但是数据范围实在太庞大了,高精度的时间复杂度是很高的,所以我们另辟蹊径。考虑到每条边边权都是\(2^x\)的形式,提示我们将起点到每个点的最短距离转化为二进制形式。考虑松弛操作需要用到什么,发现需要比较两个二进制数......
  • 2024 52pojie春节解题领红包之Windows 高级题
    202452pojie春节解题领红包之Windows高级题分析:crackme2024.exex64位程序upx脱壳,x64dbg设置异常,手动脱壳,略反调试cinit-->initterm_4定位到如下函数VEH_antiBP_140001670__int64VEH_antiBP_140001670(){qword_140020E58=findCC_1400022F0(0x64,0i64);AddVe......
  • 模拟赛 2024.2.16 解题报告
    A.楼房搭建题意:有\(n\)个数\(a_{1...n}\),以及初始全是\(0\)的\(b_{1...n}\)。现在每次选择一个\(i\in[1,n-1]\),然后选择下面一个操作:\(a_i\getsa_i+1,\spacea_{i+1}\getsa_{i+1}+2\)\(a_i\getsa_i+2,\spacea_{i+1}\getsa_{i+1}+1\)求使得\(\foralli,b......
  • 遇到过的rsa解题总结
    rsa证明c=m**emodnm=c**dmodn将式1带入式2 得 m = (m ^ e % N ) ^ d % N需要证明:m == ( m ^ e % N ) ^ d % N(me%N)d%N=>  (me)d%N #模运算 a ^ b % p = ((a % p) ^ b) % pm^(e*d)%N #幂的乘方,底数不变,指数相乘将 e * d......
  • 【解题报告】【比赛复现】洛谷入门赛 #17 题解
    洛谷入门赛#17题解今日推歌:《春嵐feat.初音ミク》john感觉这首都快成周榜战神了(Before关于我做入门赛的精神状态:没做T4,因为题面读得我头疼……而且大模拟不想做(虽然也不是多大的模拟展开目录目录洛谷入门赛#17题解BeforeA食堂B数学选择题AfterC风球E式神考核Af......
  • 【持续更新中】【解题报告】你非得用贪心解深搜题吗?——搜索题迷惑解法大赏
    寒假THOI集训部分深搜题目(另类)题解今日推歌:《カブってこうぜぇfeat.可不》-タケノコ少年特别可爱的一个歌,,,Before集训时候做题做出的怪异解法和迷惑大赏,真实有用的成分低于迷惑成分除了深搜以后(可能)还会有广搜题本篇没有任何以贪心为正解的题,也(几乎)没有以正解(搜索)做出来......
  • Codeforces 解题报告(202402)
    CodeforcesRound926D-SashaandaWalkintheCitydp,主要难点在于设状态。发现子树内一旦存在一个点,到当前子树的根节点路径上有两个危险点,那么除了那条链所属的子树,其他的点就都不能选了。所以把这个性质放进状态,设\(f_{u,0/1}\)表示以\(u\)为根的子树内,是否存在一......
  • C语言解题 || 牛牛的时钟
    题目:描述牛牛在午夜12点(0点0分0秒)正在思考,在t秒之后是什么时间。他思考了n次这个问题。输入描述:第一行输入一个正整数n。第二行输入n个正整数t,表示t秒之后。    输出描述:输出n行,每行输出t秒之后的时间。例://输入4606112//输出010//表示60秒之后是0......
  • C语言解题 || 逼近π
    题目:利用公式求m的近似值,直到发现某一项的绝对值小于10的-10次方为止(该项不累加)代码实现:#include<stdio.h>intmain(){ longdoublepi=0; longdoublesum=0; inti=0;//分母位 ints=0;//符号位 s=1;//符号起始为正 for(i=1;1.0/i>=10e-10;i+=......
  • C语言解题 || 调整数列
    题目:有n个整数,使其前面各数顺序向后移m个位置,移出的数再从头移入,使得最后m个数变成前面m个数。例:设n为6,m为2,当n个数为{1,2,3,4,5,6},函数使之变为{5,6,1,2,3,4}编写一个函数move,实现以上功能,该函数的声明如下:voidmove(int*x,intn,intm)实现思想:拿出最后一个数,然后其他数字......