To_Heart—题解——HDU6829 Borrow
题目大意
大致题意:给你三个数 a,b,c 每次操作可以选择最大的数减一,其他两个数各有 1/2 的概率加一,如果两个数都是最大的就等概率选择一个减一,其他两个数各有 1/2 的概率加一。问最后所有数相等的期望,如果期望无限大输出 -1 。
题解
先判断 -1 ,发现如果三个数加起来不是 3 的倍数肯定无解。
现在考虑其他两种情况。不妨设 a<b<c。再设一个平均数为 now。
显然 a<now,c>now。那么可以根据 b 和 now 的大小关系分为两种情况。
- 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)。 - b<now:
考虑枚举在哪一步的时候 b 和 c 里面有一个大于或等于了now,那么这个时候就可以规约到第一步。
#include<bits/stdc++.h>
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
*/
是好题吧?不会期望就是了。