zoukankan      html  css  js  c++  java
  • @loj


    @description@

    小 A 和小 B 是一对好朋友,他们经常一起愉快的玩耍。最近小 B 沉迷于**师手游,天天刷本,根本无心搞学习。但是已经入坑了几个月,却一次都没有抽到 SSR,让他非常怀疑人生。

    勤勉的小 A 为了劝说小 B 早日脱坑,认真学习,决定以抛硬币的形式让小 B 明白他是一个彻彻底底的非洲人,从而对这个游戏绝望。两个人同时抛 b 次硬币,如果小 A 的正面朝上的次数大于小 B 正面朝上的次数,则小 A 获胜。

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

    原题传送门。

    @solution@

    正着考虑要分类讨论,反着来,总方案数减不合法方案数。直接写式子:

    [2^{a+b} - sum_{i=0}^{b}{bchoose i}sum_{j=0}^{i}{achoose j} ]

    注意到 a - b 相较于 a, b 很小,尝试构造 a - b:

    [egin{aligned} sum_{i=0}^{b}{bchoose i}sum_{j=0}^{i}{achoose j} &= sum_{i=0}^{b}{bchoose i}sum_{p+qleq i}{a-bchoose q}{bchoose p} \ &= sum_{q=0}^{a-b}{a-bchoose q}sum_{i=q}^{b}sum_{i-pgeq q}{bchoose i}{bchoose p} end{aligned} ]

    注意到当 q = 0 时,有:

    [sum_{i=0}^{b}sum_{igeq p}{bchoose i}{bchoose p}=frac{1}{2}[(sum_{i=0}^{b}{bchoose i})^2 + sum_{i=0}^{b}{bchoose i}^2] ]

    而众所周知 (sum_{i=d}^{b}{bchoose i}{bchoose i-d}=sum_{i=d}^{b}{bchoose i}{bchoose b-i+d}={2bchoose b+d})。那么上式就等于 (2^{2b-1} + frac{1}{2}{2bchoose b})

    继续做变换:

    [egin{aligned} sum_{i=q}^{b}sum_{i-pgeq q}{bchoose i}{bchoose p}&=sum_{i=0}^{b}sum_{i-pgeq 0}{bchoose i}{bchoose p} - sum_{d=0}^{q-1}sum_{i=d}^{b}{bchoose i}{bchoose i-d} \ &= 2^{2b-1} + frac{1}{2}{2bchoose b} - sum_{d=0}^{q-1}{2bchoose b+d} end{aligned} ]

    然后就没了。直接上扩展 lucas 定理算组合数。

    @accepted code@

    #include <cstdio>
    #include <algorithm>
    using namespace std;
    
    typedef long long ll;
    
    const int P[2] = {2, 5}, MOD[2] = {512, 1953125}, INV[2] = {212890625, 787109376};
    
    int pow_mod(int b, ll p, int m) {
    	int ret = 1;
    	for(ll i=p;i;i>>=1,b=1LL*b*b%m)
    		if( i & 1 ) ret = 1LL*ret*b%m;
    	return ret;
    }
    
    int f[2][int(2E6) + 5], ivf[2][int(2E6) + 5];
    void init() {
    	for(int i=0;i<2;i++) {
    		f[i][0] = 1;
    		for(int j=1;j<=MOD[i];j++) {
    			if( j % P[i] ) f[i][j] = 1LL*f[i][j - 1]*j%MOD[i];
    			else f[i][j] = f[i][j - 1];
    		}
    		
    		for(int j=1;j<=MOD[i];j++)
    			if( 1LL * j * f[i][MOD[i]] % MOD[i] == 1 ) {
    				ivf[i][MOD[i]] = j;
    				break;
    			}
    		for(int j=MOD[i]-1;j>=0;j--) {
    			if( (j + 1) % P[i] ) ivf[i][j] = 1LL*ivf[i][j + 1]*(j + 1)%MOD[i];
    			else ivf[i][j] = ivf[i][j + 1];
    		}
    	}
    }
    
    int mod;
    int comb(ll n, ll m, bool flag = false) {
    	int ans = 0;
    	for(int i=0;i<2;i++) {
    		int x = 1; ll y = 0, z = 0;
    		
    		for(ll p=n;p;y+=p/P[i],z+=p/MOD[i],p/=P[i])
    			x = 1LL*x*f[i][p%MOD[i]]%MOD[i];
    		for(ll p=m;p;y-=p/P[i],z-=p/MOD[i],p/=P[i])
    			x = 1LL*x*ivf[i][p%MOD[i]]%MOD[i];
    		for(ll p=n-m;p;y-=p/P[i],z-=p/MOD[i],p/=P[i])
    			x = 1LL*x*ivf[i][p%MOD[i]]%MOD[i];
    		
    		if( flag ) {
    			if( i == 0 ) y--;
    			else x = 1LL*x*ivf[1][2]%mod;
    		}
    		
    		if( z > 0 ) x = 1LL*x*pow_mod(f[i][MOD[i]], z, MOD[i])%MOD[i];
    		else x = 1LL*x*pow_mod(ivf[i][MOD[i]], -z, MOD[i])%MOD[i];
    		
    		x = 1LL*x*pow_mod(P[i], y, MOD[i])%MOD[i];
    		ans = (ans + 1LL*x*INV[i]%mod) % mod;
    	}
    	return ans;
    }
    
    ll a, b;
    int solve() {
    	int tmp = (pow_mod(2, 2*b - 1, mod) + comb(2*b, b, true)) % mod, d = a - b, ret = 0;
    	for(int i=0;i<=d&&i<=b;i++) {
    		int k = comb(d, i);
    		ret = (ret + 1LL*k*tmp%mod) % mod;
    		tmp = (tmp + mod - comb(2*b, b + i)) % mod;
    	}
    	return (pow_mod(2, a + b, mod) + mod - ret) % mod;
    }
    
    void write(int ans, int k) {
    	if( !k ) return ;
    	write(ans / 10, k - 1);
    	putchar(ans % 10 + '0');
    }
    int main() {	
    	init();
    	for(int k,i;scanf("%lld%lld%d", &a, &b, &k)==3;) {
    		for(mod = i = 1; i <= k; i++) mod *= 10;
    		write(solve(), k), puts("");
    	}
    }
    

    @details@

    算是比较中规中矩的组合数学题吧。

    主要是我没想到我原来用的扩展 lucas 模板原来是会 TLE 的。。。
    可以实现成只剩下 O(1) 个快速幂,而不用每次都去快速幂变成 O(log) 次。。。

  • 相关阅读:
    JavaWeb图片显示与存储
    sql将日期按照年月分组并统计数量
    response的作用
    TCP/IP学习笔记(1)-----基本概念
    TCP/IP学习笔记(2)---数据链路层
    TCP/IP学习笔记(3)----IP,ARP,RARP协议
    TCP/IP学习笔记(4)------ICMP,ping,traceroute
    TCP/IP学习笔记(5)------IP选路
    如何运行简单的scrapy
    difference among String,StringBuilder,StringBuffer
  • 原文地址:https://www.cnblogs.com/Tiw-Air-OAO/p/12993801.html
Copyright © 2011-2022 走看看