1. 程式人生 > 實用技巧 >2020 hdu多校賽 第六場 1003 Borrow

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