2020 hdu多校赛 第六场 1003 Borrow

题意:

有三个整数x y z(<=1000000),每次把最大的数(如果有多个随机选)-1,再随机挑一个非最大的数+1,求这样操作直到三个数相同的期望步数。

最后15分钟想到正解,然而边界没处理好,来不及了……

我们不难发现,操作一定是经过这么一个过程(设x>=y>=z):

x  y  z

a a b / a+1 a b

c c c

所以,我们将整个过程分为两部分:

第一部分: x y z 到 a a b,且到a a b的上一步不是 a+1 a b-1 或 x y z 到a+1 a b-1,且上一步不是a+1 a+1 b。

第二部分 a a b到 c c c 或 a+1 a b-1到 c c c

对于第一部分的概率,我们可以利用组合数快速计算,期望步数就是x-a/x-(a+1)

对于第二部分的期望,通过列方程/看样例可以知道 a a b 到 a-1 a-1 b+2的期望步数是4,a+1 a b-1到 a a b的期望步数是2,所以我们可以O(1)求出期望步数,而他的概率承接第一部分的概率。

所以,我们只要枚举中间值a就可以快速求得答案。

  1 #include<iostream>
  2 #include<cstdlib>
  3 #include<cstdio>
  4 #include<cstring>
  5 #include<cmath>
  6 #include<algorithm>
  7 #define N 1000005
  8 using namespace std;
  9 const int p=998244353;
 10 int x,y,z,T;
 11 int A[10];
 12 long long jc[N],ni[N];
 13 long long ksm(long long x,long long z)
 14 {
 15     long long ans=1;
 16     while(z)
 17     {
 18         if(z&1) ans=ans*x%p;
 19         x=x*x%p;
 20         z>>=1;
 21     }
 22     return ans;
 23 }
 24 long long get_C(int x,int y)
 25 {
 26     if(x<y)return 0;
 27     return jc[x]*ni[y]%p*ni[x-y]%p;
 28 }
 29 int main()
 30 {
 31     jc[0]=ni[0]=1;
 32     for(int i=1;i<=1000000;i++) jc[i]=jc[i-1]*i%p,ni[i]=ksm(jc[i],p-2);
 33     scanf("%d",&T);
 34     while(T--)
 35     {
 36         scanf("%d%d%d",&A[1],&A[2],&A[3]);
 37         sort(A+1,A+4);
 38         x=A[3],y=A[2],z=A[1];
 39         if((x+y+z)%3)
 40         {
 41             printf("-1\n");
 42             continue;
 43         }
 44         if(x==y)
 45         {
 46             int tmp=x+y+z;
 47             tmp/=3;
 48             printf("%d\n",(x-tmp)*4);
 49         }
 50         else if(x==y+1)
 51         {
 52             int tmp=x+y+z;
 53             tmp/=3;
 54             x--;
 55             printf("%d\n",(x-tmp)*4+2);
 56         }
 57         else
 58         {
 59             long long ans=0;
 60             int tmp=x+y+z;
 61             tmp/=3;
 62             for(int i=x-1;i>tmp&&i>=y;i--)
 63             {
 64                 if(y+(x-i)<i)continue;
 65                 long long tp=ksm(ksm(2,x-i),p-2)*get_C(x-i-1,x-i-(i-y))%p;
 66             //    cout<<i<<' '<<tp<<endl;
 67                 ans+=tp*(x-i+4*(i-tmp))%p;
 68                 ans%=p;
 69             }
 70             //cout<<"Dsadasdas"<<endl;
 71             for(int i=x;i>tmp&&i>=y;i--)
 72             {
 73                 if(y+(x-i)<i-1)continue;
 74                 long long tp=ksm(ksm(2,x-i),p-2)*get_C(x-i,i-1-y)%p;
 75                 //cout<<i<<' '<<tp<<' '<<get_C(x-i,i-1-y)<<' '<<ksm(ksm(2,x-i),p-2)<<endl; 
 76                 ans+=tp*(x-i+2+4*(i-1-tmp))%p;
 77             //    cout<<' '<<(x-i+2+4*(i-1-tmp))<<endl;
 78                 ans%=p;
 79             }
 80         //    cout<<ans<<endl;
 81             swap(y,z);
 82             for(int i=x-1;i>tmp&&i>=y;i--)
 83             {
 84                 if(y+(x-i)<i)continue;
 85                 long long tp=ksm(ksm(2,x-i),p-2)*get_C(x-i-1,x-i-(i-y))%p;
 86                 ans+=tp*(x-i+4*(i-tmp))%p;
 87                 ans%=p;
 88             }
 89             for(int i=x;i>tmp&&i>=y;i--)
 90             {
 91                 if(y+(x-i)<i-1)continue;
 92                 long long tp=ksm(ksm(2,x-i),p-2)*get_C(x-i,i-1-y)%p;
 93                 ans+=tp*(x-i+2+4*(i-1-tmp))%p;
 94                 ans%=p;
 95             }
 96             printf("%lld\n",ans);
 97         }
 98     }
 99     return 0;
100 }
View Code

 

posted @ 2020-08-06 20:54  Hzoi_joker  阅读(294)  评论(0编辑  收藏  举报