To_Heart—题解——HDU6829 Borrow

题目大意

link.

大致题意:给你三个数 a,b,c 每次操作可以选择最大的数减一,其他两个数各有 1/2 的概率加一,如果两个数都是最大的就等概率选择一个减一,其他两个数各有 1/2 的概率加一。问最后所有数相等的期望,如果期望无限大输出 -1 。

题解

先判断 -1 ,发现如果三个数加起来不是 3 的倍数肯定无解。

现在考虑其他两种情况。不妨设 a

显然 anow。那么可以根据 b 和 now 的大小关系分为两种情况。

  1. b>=now :
    此时假设 f[k] 表示最小值到达 k 的期望步数。那么 f[k]=1+ 1/2 f[k+1] +1/2 f[k] ; 易知 f[now]=0,所以 f[k]=f[k+1]+2,所以 f[k]=2*(now-k)。
  2. b 考虑枚举在哪一步的时候 b 和 c 里面有一个大于或等于了now,那么这个时候就可以规约到第一步。


#include
using namespace std;
#define ll long long
#define int ll
const ll Mod=998244353;
 
ll fac[2000005];
ll inv[2000005];

ll Pow(ll a,ll b){
	ll ans=1;
	while(b){
		if(b&1) ans*=a,ans%=Mod;
		a*=a,a%=Mod,b>>=1; 
	}
	return ans;
}

void Init(int n){
	fac[0]=1;for(int i=1;i<=n;i++) fac[i]=fac[i-1]*i%Mod;
	inv[n]=Pow(fac[n],Mod-2);
	for(int i=n-1;i>=0;i--) inv[i]=inv[i+1]*(i+1)%Mod; 
}
ll C(ll n,ll m){
	if(n<0||m<0||n-m<0) return 0;
	return fac[n]*inv[m]%Mod*inv[n-m]%Mod;
}

ll X,Y,Z;
ll x,y,z;

signed main(){
	Init(1e6);
	int T;cin>>T;while(T--){
		scanf("%lld%lld%lld",&X,&Y,&Z);
		x=max(X,max(Y,Z)),z=min(X,min(Y,Z)),y=X+Y+Z-x-z;
		ll now=(x+y+z);if(now%3){ printf("-1\n");continue; }
		now/=3;x-=now,y-=now,z-=now;
		if(y>=0) printf("%lld\n",(-z*2)%Mod);
		else{
			ll now=0;y=-y,z=-z;
//			printf("qwq::%lld %lld\n",y,z);
			for(ll i=y;i<=x-1;i++){
				now+=C(i-1,z-1)*(i+2*(x-i))%Mod*Pow(Pow(2,i),Mod-2)%Mod,now%=Mod;
				now+=C(i-1,y-1)*(i+2*(x-i))%Mod*Pow(Pow(2,i),Mod-2)%Mod,now%=Mod;
//				printf("%lld:%lld %lld\n",i,C(i-1,z-1),C(i-1,y-1));
			}
			printf("%lld\n",now);
		}
	}	
	return 0;
}
/*
1
114 514 191
*/

是好题吧?不会期望就是了。

你可能感兴趣的:(算法,c++,数据结构)