当前位置: 首页 > 工具软件 > Nanning > 使用案例 >

ACM-ICPC 2017 Asia Nanning E - The Champion

贺立果
2023-12-01

ACM-ICPC 2017 Asia Nanning E - The Champion

题意: 有r场对局,2^r个人,你在当中实力排在第k位,当一个强的人跟弱的人打的时候,强的人赢的概率是p。你可以自由安排大家对局,最后留下来的人是胜者,问怎么安排对局你自己的胜率最高,最高是多少,输出。
思路: 我们很容易想到你只有多更比你弱的人打,你成为最终胜者的概率才会越高。所以最优的情况是你跟弱者打,强者内部打,弱者内部打。直到一方没有。但是有个问题就是当强者的人数时奇数时,你就需要判断两种情况,一种是强者赢了,一种是强者输了。最后我们按最优的方法打就行了。用dfs来递归。(记得加上记忆化搜索,没加会超时,亲身经历)

#include<bits/stdc++.h>
using namespace std;
#define double long double
typedef unsigned long long ll;
ll r,k;
double p;
map<pair<ll,ll>,double >mp;
double qpow(double a,int b)
{
	double ans=1.0;
	while(b!=0)
	{
		if(b&1){
			ans*=a;
		}
		a=a*a;
		b>>=1;
	}
	return ans;
}
double dfs(ll a,ll b)
{
	if(mp.find({a,b})!=mp.end()){
		return mp[{a,b}];
	}
	if(a==0){
		int e=b;
		b++;
		int cnt=0;
		for(int i=1;i<=64;i++){
			b>>=1;
			if(b==1){
				cnt=i;
				break;
			}
		}
		mp[{a,e}]=qpow(p,cnt);
		return mp[{a,e}];
	}
	if(b==0){
		int e=a;
		a++;
		int cnt=0;
		for(int i=1;i<=64;i++){
			a>>=1;
			if(a==1){
				cnt=i;
				break;
			}
		}
		mp[{e,b}]=qpow(1.0-p,cnt);
		return mp[{e,b}];
	}
	double maxx=1;
	if(a%2==0){
		double x=dfs(a>>1,(b>>1))*p;
		mp[{a,b}]=x;
		return x;
	}else{
		double x1=dfs((a>>1)+1,(b>>1)-1)*p*p;
		double x2=dfs(a>>1,b>>1)*p*(1-p);
		mp[{a,b}]=x1+x2;
		return x1+x2;
	}
}
int main()
{
	ll t;
	scanf("%lld",&t);
	while(t--)
	{
		scanf("%lld%lld%Lf",&r,&k,&p);
		ll a=k-1;
		ll b=(1ll<<r)-k;
		if(p<0.5){
			swap(a,b);
			p=1-p;
		}
		mp.clear();
		mp[{0,1}]=p;
		mp[{1,0}]=1.0-p;
		double ans=dfs(a,b);
		printf("%.6Lf\n",ans);
	}
	return 0;
}
 类似资料: