hdu6829 | 杭电多校2020#6 T3 Borrow

标算是什么乱七八糟的东西(


\(m=\frac{x+y+z}{3},x\ge y \ge z\)

注意到给钱的顺序与最后的结果完全无关,所以可以让原来最多的人先给出 \(x-m\) 元钱,此时会得到 \(m+a,m,m-a\) 的形式,其中 \(a\) 是一个不确定且可以枚举的数,这和 \(0,c,2c\) 是本质相同的。

\(f_x\) 表示 \(0,x,2x\) 状态下的期望步数,则 \(f_x=x+\sum\limits_{i=0}^x \frac{1}{2^x}\binom{x}{i}f_i\) ,即原来是 \(2x\) 的人必须给出 \(x\) 元,并对结果分类讨论,然后打表可得 \(f_x=2x\) ,应该可以归纳证明。

所以就做完了,(比标算好想好写)

Code:

#include<bits/stdc++.h>
using namespace std;
#define mod 998244353
#define inf 0x3f3f3f3f
inline int read()
{
	char ch=getchar(); int nega=1; while(!isdigit(ch)) {if(ch=='-') nega=-1; ch=getchar();}
	int ans=0; while(isdigit(ch)) {ans=ans*10+ch-48;ch=getchar();}
	if(nega==-1) return -ans;
	return ans;
}
#define N 2000005
inline int add(int x,int y){return x+y>=mod?x+y-mod:x+y;}
inline int mul(int x,int y){return 1LL*x*y%mod;}
inline int mul(int x,int y,int z){return mul(mul(x,y),z);}
int qpow(int x,int y)
{
	int ans=1;
	while(y)
	{
		if(y&1) ans=mul(ans,x);
		x=mul(x,x);
		y>>=1;
	}
	return ans;
}
int Inv(int x){return qpow(x,mod-2);}
int fac[N],inv[N],pinv[N],pw[N];
void init()
{
	pw[0]=1; for(int i=1;i<N;i++) pw[i]=mul(pw[i-1],2);
	fac[0]=1; for(int i=1;i<N;i++) fac[i]=mul(fac[i-1],i);
	inv[0]=inv[1]=1; for(int i=2;i<N;i++) inv[i]=mul(mod-mod/i,inv[mod%i]);
	pinv[0]=1; for(int i=1;i<N;i++) pinv[i]=mul(pinv[i-1],inv[i]);
}
int C(int x,int y){return x>=y?mul(fac[x],pinv[x-y],pinv[y]):0;}
int a[5];
void work()
{
	for(int i=1;i<=3;i++) a[i]=read();
	sort(a+1,a+4,[&](int x,int y){return x>y;});
	if((a[1]+a[2]+a[3])%3!=0)
	{
		cout<<"-1\n";
		return ;
	}
	int m=(a[1]+a[2]+a[3])/3,ans=0;
	for(int i=0;i<=(a[1]-m);i++)
	{
		int cur=abs(a[3]+i-m);
		ans=add(ans,mul(C(a[1]-m,i),cur*2));
	}
	printf("%d\n",add(mul(ans,Inv(pw[a[1]-m])),a[1]-m));
}
signed main()
{
	init();
	int T=read(); while(T--) work();
	return 0;
}
posted @ 2020-08-06 19:01  wasa855  阅读(387)  评论(0编辑  收藏  举报