ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

省选测试18

2021-02-07 22:32:36  阅读:169  来源: 互联网

标签:ch 省选 18 int while rg 测试 include getchar


A. 飞行棋

分析

因为这道题的期望不是模意义下的

所以在迭代多次之后精度就会达到要求

设 \(f[i][j]\) 为第\(i\) 轮在位置 \(j\) 的人获胜的概率

随便转移一下就行了

转移的时候记录一个变量 \(p\) 表示当前有多少概率所有人都没赢

如果 \(p<1e-8\) 直接退出循环

注意当前的位置的人获胜的概率还要乘上其它的人在这个人之前不获胜的概率

代码

#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#define rg register
inline int read(){
	rg int x=0,fh=1;
	rg char ch=getchar();
	while(ch<'0' || ch>'9'){
		if(ch=='-') fh=-1;
		ch=getchar();
	}
	while(ch>='0' && ch<='9'){
		x=(x<<1)+(x<<3)+(ch^48);
		ch=getchar();
	}
	return x*fh;
}
const int maxn=163;
int n,a[maxn],b[maxn],m;
double f[2][maxn],ans[maxn],p=1.0,gl[maxn];
int main(){
	n=read(),m=read();
	for(rg int i=1;i<=n;i++) a[i]=read();
	for(rg int i=1;i<=m;i++) b[i]=read(),gl[i]=1.0;
	a[n+1]=a[n+2]=a[n+3]=a[n+4]=a[n+5]=n;
	rg int now=0;
	f[now][n]=1.0;
	for(rg int i=1;;i++){
		now^=1;
		memset(f[now],0,sizeof(f[now]));
		for(rg int j=1;j<n;j++){
			for(rg int k=1;k<=6;k++){
				f[now][j]+=f[now^1][a[j+k]];
			}
			f[now][j]/=6.0;
		}
		for(rg int j=1;j<=m;j++){
			if(f[now][b[j]]){
				p/=gl[j];
				ans[j]+=p*f[now][b[j]];
				gl[j]-=f[now][b[j]];
				p*=gl[j];
			}
		}
		if(p<1e-8) break;
	}
	for(rg int i=1;i<=m;i++) printf("%.6f\n",ans[i]);
	return 0;
}

B. 字符串难题

分析

把问题转化一下:求所有情况下本质不同的前缀个数之和

发现这个东西不太好求,而且 \(n\) 的范围只有 \(20\),所以考虑容斥

可以把本质不同的前缀看成集合的并,把公共前缀看成集合的交

那么答案就是元素个数为 \(1\) 的集合的交减去元素个数为 \(2\) 的集合的交加上元素个数为 \(3\) 的集合的交\(\cdots\)

设 \(E(lcp(S))\) 为集合 \(S\) 中公共前缀的期望

那么最终的答案就是 \(\sum\limits_{S\subseteq A}(-1)^{|S|-1}E(lcp(s))\)

只要求出 \(E(lcp(S))\) 就行了

这个东西我们可以枚举每一个位置的贡献

设 \(f[i]\) 为 \(S\) 中的所有串的公共前缀长度为 \(i\),同时不考虑 \(i\) 以后的部分的影响的情况下的方案

设所有串中共含有 \(totcnt\) 个 \(?\),当前已经遍历了 \(nowcnt\) 个 \(?\)

如果所有 \(S\) 集合中的串第 \(i\) 位都是 \(?\)

那么可以全填 \(0\) 或者全填 \(1\),显然 \(f[i]=2 \times f[i-1]\)

如果只能全填 \(0\) 或者全填 \(1\)

那么 \(f[i]=f[i-1]\)

如果第 \(i\) 位上既有 \(0\) 又有 \(1\),即发生了冲突,就不能转移,方案数置为 \(0\)

最终的贡献 \(E(lcp(S))=\sum\limits_{i=1}^{min(len[i],i \in S)}f[i] \times 2^{totcnt-nowcnt}\)

因为 \(trie\) 树上还有一个空节点,所以最后还要把把前缀为空的贡献 \(2^{totcnt}\) 加上

代码

#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#define rg register
inline int read(){
	rg int x=0,fh=1;
	rg char ch=getchar();
	while(ch<'0' || ch>'9'){
		if(ch=='-') fh=-1;
		ch=getchar();
	}
	while(ch>='0' && ch<='9'){
		x=(x<<1)+(x<<3)+(ch^48);
		ch=getchar();
	}
	return x*fh;
}
const int maxn=1e3+5,mod=998244353;
inline int addmod(rg int now1,rg int now2){
	return now1+=now2,now1>=mod?now1-mod:now1;
}
char s[maxn][maxn];
int n,len[maxn],totcnt,ans,mmax,mi[maxn];
int main(){
	n=read();
	for(rg int i=1;i<=n;i++){
		scanf("%s",s[i]+1);
		len[i]=strlen(s[i]+1);
		for(rg int j=1;j<=len[i];j++){
			if(s[i][j]=='?') totcnt++;
		}
	}
	mi[0]=1;
	for(rg int i=1;i<=totcnt;i++) mi[i]=addmod(mi[i-1],mi[i-1]);
	mmax=(1<<n)-1,ans=mi[totcnt];
	rg int siz,minlen,nans,jud0,jud1,ncnt;
	for(rg int i=1;i<=mmax;i++){
		siz=0,minlen=0x3f3f3f3f,nans=0,ncnt=totcnt;
		for(rg int j=1;j<=n;j++){
			if(i&(1<<(j-1))) siz++,minlen=std::min(minlen,len[j]);
		}
		for(rg int j=1;j<=minlen;j++){
			jud0=jud1=0;
			for(rg int k=1;k<=n;k++){
				if(i&(1<<(k-1))){
					if(s[k][j]=='0')jud0=1;
					else if(s[k][j]=='1')jud1=1;
					else ncnt--;
				}
			}
			if(jud0 && jud1) break;
			if(!jud0 && !jud1) ncnt++;
			nans=addmod(nans,mi[ncnt]);
		}
		if(siz&1) ans=addmod(ans,nans);
		else ans=addmod(ans,mod-nans);
	}
	printf("%d\n",ans);
	return 0;
}

C. 障碍雷达

分析

首先可以发现,收益是个初值为 \(0\) 的二次函数,代价是一次函数

那么可以猜想必然存在一种最优解,使得每个雷达要么选最大的纵坐标,要么不选

然后就有了 \(n^2\) 的做法

然后就有了 \(300n\) 的做法

貌似这道题还可以按照右端点排序后在线段树上维护凸包进行斜率优化,不过 \(1e6\) 的范围可能有亿点悬

代码

#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#define rg register
inline int read(){
	rg int x=0,fh=1;
	rg char ch=getchar();
	while(ch<'0' || ch>'9'){
		if(ch=='-') fh=-1;
		ch=getchar();
	}
	while(ch>='0' && ch<='9'){
		x=(x<<1)+(x<<3)+(ch^48);
		ch=getchar();
	}
	return x*fh;
}
const int maxn=1e6+5;
int t,n;
long long f[maxn],ans;
struct asd{
	int l,r;
	long long val;
}b[maxn];
bool cmp(rg asd aa,rg asd bb){
	return aa.r<bb.r;
}
long long pf(rg long long aa){
	return aa*aa;
}
int main(){
	t=read();
	while(t--){
		n=read();
		rg int aa,bb,cc;
		for(rg int i=1;i<=n;i++){
			aa=read(),bb=read(),cc=read();
			b[i].l=aa-bb,b[i].r=aa+bb,b[i].val=4LL*pf(bb)-4LL*bb*cc;
		}
		std::sort(b+1,b+1+n,cmp);
		for(rg int i=1;i<=n;i++) f[i]=0;
		for(rg int i=1;i<=n;i++){
			f[i]=std::max(f[i],b[i].val);
			for(rg int j=std::max(1,i-300);j<i;j++){
				f[i]=std::max(f[i],f[j]+b[i].val-pf(std::max(0,b[j].r-b[i].l)));
			}
		}
		ans=0;
		for(rg int i=1;i<=n;i++) ans=std::max(ans,f[i]);
		if(ans%4==0) printf("%lld.00\n",ans/4);
		else if(ans%4==1) printf("%lld.25\n",ans/4);
		else if(ans%4==2) printf("%lld.50\n",ans/4);
		else printf("%lld.75\n",ans/4);
	}
	return 0;
}

标签:ch,省选,18,int,while,rg,测试,include,getchar
来源: https://www.cnblogs.com/liuchanglc/p/14386846.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有