• bzoj4830 hnoi2017 抛硬币


    题目描述

    小 A 和小 B 是一对好朋友,他们经常一起愉快的玩耍。最近小 B 沉迷于**师手游,天天刷本,根本无心搞学习。但是已经入坑了几个月,却一次都没有抽到 SSR,让他非常怀疑人生。勤勉的小 A 为了劝说小 B 早日脱坑,认真学习,决定以抛硬币的形式让小 B 明白他是一个彻彻底底的非洲人,从而对这个游戏绝望。两个人同时抛 b 次硬币,如果小 A 的正面朝上的次数大于小 B 正面朝上的次数,则小 A 获胜。

    但事实上,小 A 也曾经沉迷过拉拉游戏,而且他一次 UR 也没有抽到过,所以他对于自己的运气也没有太大把握。所以他决定在小 B 没注意的时候作弊,悄悄地多抛几次硬币,当然,为了不让小 B 怀疑,他不会抛太多次。现在小 A 想问你,在多少种可能的情况下,他能够胜过小 B 呢?由于答案可能太大,所以你只需要输出答案在十进制表示下的最后 k 位即可。

    输入输出格式

    输入格式:

     

    有多组数据,对于每组数据输入三个数a,b,k,分别代表小A抛硬币的次数,小B抛硬币的次数,以及最终答案保留多少位整数。

     

    输出格式:

     

    对于每组数据,输出一个数,表示最终答案的最后 k 位为多少,若不足 k 位以 0 补全。

    题意:

    小A可以抛a次硬币,小B可以抛b次硬币(a>=b)问小A抛出正面的次数比小B多的情况种数,输出对10的k次方取余(k<=9);

    题解:

    ①这是一个利用对应关系进行构造的组合问题:

    如果每一种小A赢情况对应(把a,b次抛出的结果正面变成反面)一种小B赢的情况,那么总可能数/2就是答案,但是事实上不是,在可能会有小A无论在两种情况下都是比小B多,或者小A在两种情况下都小于等于小B的次数,为此,就只有分a=b和a>b讨论。

    a=b

    A和B掷出的正面相同,小A两种情况都赢不了

    $F = sum_{i=0}^{a}C_{a}^{i}C_{a}^{i}=sum_{i=0}^{a}C_{a}^{i}C_{a}^{a-i} = C_{2a}^{a}$

    (a选i个再在另外a个选a-i个和在2a个里选a个一一对应)

    $ans = frac{2^{2a}-F}{2} = frac{2^{2a}-C_{2a}^{a}}{2}$

    a>b

    A和B掷出的正面满足A>B且a-A>b-B时小A两种情况都可以赢小B

    $G = sum_{i=0}^{b}sum_{j=1}^{a-b-1}C_{b}^{i}C_{a}^{i+j} = sum_{i=0}^{b}sum_{j=1}^{a-b-1}C_{b}^{b-i}C_{a}^{i+j} = sum_{j=1}^{a-b-1}C_{a+b}^{j+b}$ 

    (b个里选b-i个再在a个里选i+j个一一对应在a+b个里选b+j个)

    $ans = frac{2^{2a}+G}{2} = frac{2^{2a}+sum_{j=1}^{a-b-1}C_{a+b}^{j+b}}{2}$

    剩下的组合数取模用扩展lucas就好了,只是稍稍有点变化。

     

     1 #include<cstdio>
     2 #include<iostream>
     3 #define ll long long
     4 #define Maxn 1000000001
     5 #define RG register
     6 #define il inline
     7 using namespace std;
     8 ll a,b,K,mod,mod2,mod5,v[2][2500005];
     9 ll pw(ll x,ll y,ll Mod){
    10     ll res = 1;
    11     while(y){
    12         if(y&1) res = res * x % Mod; 
    13         y>>=1; x = x * x % Mod;
    14     }
    15     return res;
    16 }
    17 void init(ll k,ll mx){
    18     ll typ = k!=2;
    19     v[typ][0] = 1;
    20     for(RG ll i = 1;i <= mx;i++){
    21         if(i%k) v[typ][i] = v[typ][i - 1]*i % mx; 
    22         else v[typ][i] = v[typ][i - 1];
    23     }
    24 }
    25 inline void exgcd(ll a,ll b,ll &x,ll &y){
    26     if(!b) {x = 1,y = 0;}
    27     else exgcd(b,a%b,y,x),y -= a/b*x;
    28 }
    29 ll inv(ll a,ll p){
    30     ll x,y; exgcd(a,p,x,y); 
    31     return (x%p+p)%p;
    32 }
    33 il ll mul(ll n,ll p,ll pk){
    34     if(!n) return 1;
    35     ll ret = pw(v[p!=2][pk],n / pk,pk) * v[p!=2][n % pk] % pk;
    36     return ret * mul(n / p,p,pk) % pk;
    37 }
    38 ll C(ll n,ll m,ll p,ll pk,ll fg){
    39     if(n<m) return 0;
    40     ll cnt = 0;
    41     for(RG ll i = n;i;i/=p) cnt += i / p;
    42     for(RG ll i = m;i;i/=p) cnt -= i / p;
    43     for(RG ll i = (n - m);i;i/=p) cnt -= i / p;
    44     if(p==2&&fg) cnt--; 
    45     if(cnt>=K) return 0;
    46     ll s1 = mul(n,p,pk),s2 = mul(m,p,pk),s3 = mul(n - m,p,pk); 
    47     ll ret = pw(p,cnt,pk) * s1 % pk * inv(s2,pk) % pk * inv(s3,pk) % pk;
    48     if(p==5&&fg) ret = ret * inv(2,pk) % pk;
    49     return ret * (mod / pk) % mod * inv(mod / pk,pk) % mod;
    50 }
    51 ll lucas(ll n,ll m,ll fg) {return (C(n,m,2,mod2,fg) + C(n,m,5,mod5,fg)) % mod;}
    52 int main()
    53 {    //freopen("bzoj4830.in","r",stdin);
    54     //freopen("bzoj4830.out","w",stdout);
    55     init(2,512); init(5,1953125);
    56     while(cin >> a >> b >> K){
    57         mod2 = pw(2,K,Maxn); mod5 = pw(5,K,Maxn); mod = pw(10,K,Maxn);
    58         ll ans = pw(2,a + b - 1,mod);
    59         if(a==b) ans = (ans - lucas(a+b,a,1) + mod) % mod;
    60         else {
    61             for(RG ll i = (a+b)/2+1;i<a;i++) ans = (ans + lucas(a+b,i,0))%mod;
    62             if(!((a+b)%2)) ans = (ans + lucas(a+b,(a+b)/2,1)) % mod; 
    63         }
    64         while(ans<mod/10) mod/=10,printf("0");
    65         printf("%lld
    ",ans);
    66     }
    67     return 0;
    68 }//by tkys_Austin;

    (快省选了,关于扩lucas,扩gcd,扩CRT的叙述后面有时间可能会补上)

  • 相关阅读:
    Qt学习之路,part1
    1.获取状态栏的高度
    如何在Android Studio中上传代码到Gitee上
    关于类图
    外观模式
    关于类的实例
    SharedPreference中关于editor.apply()和editor.commit()
    活动的4种启动模式
    unittest中case批量管理
    unittest使用
  • 原文地址:https://www.cnblogs.com/Paul-Guderian/p/8647074.html
Copyright © 2020-2023  润新知