zoukankan      html  css  js  c++  java
  • [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 补全。

    输入输出样例

    输入样例#1: 复制
    2 1 9
    3 2 1
    输出样例#1: 复制
    000000004
    6

    说明

    对于第一组数据,当小A抛2次硬币,小B抛1次硬币时,共有4种方案使得小A正面朝上的次数比小B多。

    (01,0), (10,0), (11,0), (11,1)

    对于第二组数据,当小A抛3次硬币,小B抛2次硬币时,共有16种方案使得小A正面朝上的次数比小B多。

    (001,00), (010,00), (100,00), (011,00), (101,00), (110,00), (111,00), (011,01), (101,01), (110,01),(111,01), (011,10), (101,10), (110,10), (111,10), (111,11).

    数据范围

    10%的数据满足a,b≤20;

    30%的数据满足a,b≤100;

    70%的数据满足a,b≤100000,其中有20%的数据满足a=b;

    100%的数据满足1≤a,b≤1015,b≤a≤b+10000,1≤k≤91le a,ble 10^{15},ble ale b+10000,1le kle 91a,b1015,bab+10000,1k9,数据组数小于等于10。

    习惯交换a,b.
    先考虑ab都相等的情况.
    每个硬币只有正反两种情况,所以在把一种B的获胜态翻转就会变成A的获胜态.
    一共有2^(a+b)种情况.
    那么答案为
    平局的情况:
    这个东西好像叫范德蒙德卷积.感性证明:
    把2a均分为两组,那么从两组中一共取a个的方案数=分别从两组中取i个和a-i个的方案数.
    现在讨论b>a的情况.
    首先,a的获胜态翻转后必定是b的获胜态,但b的获胜态翻转不一定是a的获胜态.
    若能够求出所有的b的获胜态且翻转时候还是b的获胜态的数量,记为S.
    那么答案就是
    现在只需求出S.

    其中用到了范德蒙德卷积.
    然后就用扩展Lucas算出来就可以了.
    扩展Lucas:
    用来求n!mod p^k.
    可以把n!分为两类:
    1.p的倍数,这些项提取p之后又是一个新的阶乘,递归处理即可.提取的p不要算进去,最后一起算.
    2.其他项.可以发现,在模p^k的意义下,其他项会构成循环,最后不满的循环也不会超过p^k个,暴力搞就可以了.

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstdlib>
      4 #include<cstring>
      5 #include<string>
      6 #include<algorithm>
      7 #include<map>
      8 #include<complex>
      9 #include<queue>
     10 #include<stack>
     11 #include<cctype>
     12 #include<cmath>
     13 #include<set>
     14 #include<vector>
     15 #define RG register
     16 #define mk make_pair
     17 #define pb push_back
     18 #define fi first
     19 #define se second
     20 #define UN unsigned
     21 #define LL long long
     22 using namespace std;
     23 int pw[10]={1,10,100,1000,10000,100000,1000000,10000000,100000000,1000000000};
     24 int k,mod,p1,p2,jc[2][2000000];
     25 LL a,b;
     26 bool flag=0;
     27 inline void exgcd(RG LL aa,RG LL bb,RG LL &x,RG LL &y){
     28   if(bb==0) x=1,y=0;
     29   else exgcd(bb,aa%bb,y,x),y-=(aa/bb)*x;
     30 }
     31 inline LL Inv(RG LL aa,RG LL p){
     32   LL x,y;exgcd(aa,p,x,y);
     33   return (x+p)%p;
     34 }
     35 inline LL qpow(RG LL x,RG LL y,RG LL p){
     36   RG LL ans=1;
     37   while(y){
     38     if(y&1) ans=ans*x%p;
     39     y>>=1;
     40     x=x*x%p;
     41   }
     42   return ans;
     43 }
     44 inline void prepare(){
     45   p1=1,p2=1;
     46   for(RG int i=1;i<=k;i++) p1*=2,p2*=5;
     47   jc[0][0]=jc[1][0]=1;
     48   for(RG int i=1;i<=1999000;i++){
     49     if(i%2)jc[0][i]=(LL)jc[0][i-1]*i%p1;else jc[0][i]=jc[0][i-1];
     50     if(i%5)jc[1][i]=(LL)jc[1][i-1]*i%p2;else jc[1][i]=jc[1][i-1];
     51   }
     52 }
     53 inline LL Fac1(RG LL x){
     54   if(x==0) return 1;
     55   RG LL re=jc[0][p1];
     56   re=qpow(re,x/p1,p1);
     57   re=(re*jc[0][x%p1])%p1;
     58   return re*Fac1(x/2)%p1;
     59 }
     60 inline LL Fac2(RG LL x){
     61   if(x==0) return 1;
     62   RG LL re=jc[1][p2];
     63   re=qpow(re,x/p2,p2);
     64   re=(re*jc[1][x%p2])%p2;
     65   return re*Fac2(x/5)%p2;
     66 }
     67 inline LL calc1(RG LL n,RG LL m){
     68   if(n<m) return 0;
     69   RG LL c=0;
     70   for(RG LL i=n;i;i/=2) c+=i/2;
     71   for(RG LL i=m;i;i/=2) c-=i/2;
     72   for(RG LL i=n-m;i;i/=2) c-=i/2;if(flag) c--;
     73   if(c>=k) return 0;
     74   RG LL x=Fac1(n),y=Fac1(m),z=Fac1(n-m);
     75   RG LL aa=(x*Inv(y,p1)%p1*Inv(z,p1)%p1)%p1*qpow(2,c,p1)%p1;
     76   return (aa*(mod/p1)%mod*Inv(mod/p1,p1)%mod)%mod;
     77 }
     78 inline LL calc2(LL n,LL m){
     79   if(n<m) return 0;
     80   RG LL c=0;
     81   for(RG LL i=n;i;i/=5) c+=i/5;
     82   for(RG LL i=m;i;i/=5) c-=i/5;
     83   for(RG LL i=n-m;i;i/=5) c-=i/5;
     84   if(c>=k) return 0;
     85   RG LL x=Fac2(n),y=Fac2(m),z=Fac2(n-m);
     86   RG LL aa=(x*Inv(y,p2)%p2*Inv(z,p2)%p2)%p2*qpow(5,c,p2)%p2;
     87   if(flag) aa=aa*Inv(2,p2)%p2;
     88   return (aa*(mod/p2)%mod*Inv(mod/p2,p2)%mod)%mod;
     89 }
     90 inline LL exlucas(RG LL n,RG LL m){
     91   RG LL a1=calc1(n,m),a2=calc2(n,m);
     92   return (a1+a2)%mod;
     93 }
     94 int main(){
     95   freopen("!.in","r",stdin);
     96   freopen("!.out","w",stdout);
     97   while(scanf("%lld%lld%d",&a,&b,&k)!=EOF){
     98     swap(a,b);mod=pw[k];
     99     RG LL s=0;flag=0;
    100     prepare();
    101     if(a!=b) for(RG LL i=a+1;i<=(a+b-1)/2;i++) s=(s+exlucas(a+b,i))%mod;
    102     if((a+b)%2==0) flag=1,s=(s+exlucas(a+b,(a+b)/2))%mod;
    103     if(a==b) s=(mod-s)%mod;
    104     RG LL ans=(qpow(2,a+b-1,mod)+s)%mod;
    105     for(RG int i=k-1;i>=0;i--)
    106       printf("%d",ans/pw[i]),ans%=pw[i];
    107     printf("
    ");
    108   }
    109   return 0;
    110 }
    
    
    
     
  • 相关阅读:
    DOM_节点操作创建表格
    表单提交
    HTML常用标签
    网络通讯详解
    java===TCP(多线程多客户端同时上传字节数据:图片为例)
    java===TCP(文件上传功能)
    java===UDP
    java==IO=随机读写文件
    git中的基本命令
    ansible中roles的简单使用
  • 原文地址:https://www.cnblogs.com/pantakill/p/7954251.html
Copyright © 2011-2022 走看看