• jzoj 5079. 【GDOI2017第三轮模拟day2】抛硬币


    (Solution)

    对于答案,我们可以搞搞搞,最后搞出来一个:

    [Ans = ∑_{i=0}^{a-1}C(i,a+b)=∑_{i=b+1}^{a+b}C(i,a+b) ]

    所以我们可以发现:$$Ans = (2{a+b}+∑_{i=b+1}{a-1}C(i,a+b))/2$$
    由于(a-b<=10000),所以我们可以暴力求出右边的东西。
    现在的问题就是如何求(C(n,m)%10^10),我们可以用扩展lucas定理来搞。
    具体看码吧。

    (Code)

    #include <cstdio>
    #define N 100000
    #define mo 10000000000ll
    #define ll long long
    #define mo2 1024
    #define mo5 9765625
    #define fo(x, a, b) for (int x = (a); x <= (b); x++)
    using namespace std;
    int h2[1000010], h5[1000010];
    ll v2[1035], v5[9765636];
    ll a, b, K, ans;
    
    inline int read() {
    	int x = 0, f = 0; char c = getchar();
    	while (c < '0' || c > '9') f = (c == '-') ? 1 : f, c = getchar();
    	while (c >= '0' && c <= '9') x = (x << 1) + (x << 3) + (c ^ 48), c = getchar();
    	return f ? -x : x;
    }
    
    ll ksc(ll x, ll y, ll mm) {
    	ll s = 0;
    	while (y) {
    		if (y & 1) s = (s + x) % mm;
    		x = (x + x) % mm, y >>= 1;
    	}
    	return s;
    }
    
    ll ksm(ll x, ll y, ll mm) {
    	if (y == 0) return 1;
    	ll s = 1;
    	while (y) {
    		if (y & 1) s = ksc(s, x, mm);
    		x = ksc(x, x, mm), y >>= 1;
    	}
    	return s;
    }
    
    void prepare() {
    	h2[1] = 0; fo(i, 2, 1000000) h2[i] = h2[i / 2] + i / 2;
    	h5[1] = 0; fo(i, 2, 1000000) h5[i] = h5[i / 5] + i / 5;
    	v2[0] = v2[1] = v2[2] = 1;
    	fo(i, 3, mo2)
    		if (! (i & 1)) v2[i] = v2[i - 1];
    		else v2[i] = v2[i - 1] * i % mo2;
    	v5[0] = v5[1] = 1;
    	fo(i, 2, mo5)
    		if (i % 5 == 0) v5[i] = v5[i - 1];
    		else v5[i] = v5[i - 1] * i % mo5;
    }
    
    ll exgcd(ll a, ll b, ll &x, ll &y);
    
    ll hav_2(ll x) {
    	if (x <= 1000000) return h2[x];
    	return hav_2(x / 2) + (x / 2);
    }
    
    ll get_2(ll x) {
    	if (x == 0) return 1;
    	ll s = ksm(v2[mo2 - 1], x / mo2, mo2) * v2[x % mo2] % mo2;
    	return get_2(x / 2) * s % mo2;
    }
    
    ll solve_2(ll x, ll y) {
    	ll s = 1, s1 = hav_2(y), s2 = hav_2(x) + hav_2(y - x);
    	if (s1 - s2 >= 10) return 0;
    	fo(i, 1, s1 - s2) s = s << 1;
    	s1 = get_2(y), s2 = get_2(x) * get_2(y - x) % mo2;
    	ll x_, y_; exgcd(s2, mo2, x_, y_); x_ = (x_ % mo2 + mo2) % mo2;
    	s = s * s1 % mo2 * x_ % mo2;
    	return s;
    }
    
    ll hav_5(ll x) {
    	if (x <= 1000000) return h5[x];
    	return hav_5(x / 5) + (x / 5);
    }
    
    ll get_5(ll x) {
    	if (x == 0) return 1;
    	ll s = ksm(v5[mo5 - 1], x / mo5, mo5) * v5[x % mo5] % mo5;
    	return get_5(x / 5) * s % mo5;
    }
    
    ll solve_5(ll x, ll y) {
    	ll s = 1, s1 = hav_5(y), s2 = hav_5(x) + hav_5(y - x);
    	if (s1 - s2 >= 10) return 0;
    	fo(i, 1, s1 - s2) s = s * 5;
    	s1 = get_5(y), s2 = get_5(x) * get_5(y - x) % mo5;
    	ll x_, y_; exgcd(s2, mo5, x_, y_); x_ = (x_ % mo5 + mo5) % mo5;
    	s = s * s1 % mo5 * x_ % mo5;
    	return s;
    }
    
    ll exgcd(ll a, ll b, ll &x, ll &y) {
    	if (! b) {x = 1, y = 0; return a;}
    	ll t = exgcd(b, a % b, y, x);
    	y = y - a / b * x; return t;
    }
    
    ll C(ll x, ll y) {
    	ll s1 = solve_2(x, y), s2 = solve_5(x, y);
    	ll x_, y_; ll gd = exgcd(mo2, mo5, x_, y_);
    	x_ = x_ * (s2 - s1) / gd, y_ = y_ * (s2 - s1) / gd;
    	ll S = ((mo2 * x_ + s1) % mo + mo) % mo;
    	return S;
    }
    
    int main()
    {
    	freopen("coin.in", "r", stdin);
    	freopen("coin.out", "w", stdout);
    	prepare();
    	while (scanf("%lld%lld%lld", &a, &b, &K) != EOF) {
    		ll mod = 1; fo(i, 1, K) mod = mod * 10;
    		ans = ksm(2, a + b - 1, (ll)mo2 * mo5);
    		if (a > b) {
    			if ((a - b + 1) % 2 == 0) {
    				ll le = b + 1, ri = (a + b - 1) / 2;
    				for (ll i = le; i <= ri; i++)
    					ans = (ans + C(i, a + b)) % mo;
    			}
    			else {
    				ans = (ans + C((a + b) / 2, a + b) / 2) % mo;
    				ll le = b + 1, ri = (a + b) / 2 - 1;
    				for (ll i = le; i <= ri; i++)
    					ans = (ans + C(i, a + b)) % mo;
    			}
    		}
    		else ans = (ans + mo - C((a + b) / 2, a + b) / 2) % mo;
    		ans = ans % mod;
    		switch (K) {
    			case 1:printf("%01lld
    ", (ll)ans); break;
    			case 2:printf("%02lld
    ", (ll)ans); break;
    			case 3:printf("%03lld
    ", (ll)ans); break;
    			case 4:printf("%04lld
    ", (ll)ans); break;
    			case 5:printf("%05lld
    ", (ll)ans); break;
    			case 6:printf("%06lld
    ", (ll)ans); break;
    			case 7:printf("%07lld
    ", (ll)ans); break;
    			case 8:printf("%08lld
    ", (ll)ans); break;
    			case 9:printf("%09lld
    ", (ll)ans); break;
    		}
    	}
    	return 0;
    }
    
    转载需注明出处。
  • 相关阅读:
    CPLD
    红牛的广告:你的能量超乎你的想象
    Verilog设计中的锁存器
    Verilog语言
    看技术看不懂,看不进去的解决方案
    jQuery Ajax 操作函数
    Html的Padding,Margin自己理解图
    【深度好文】多线程之WaitHandle-->派生-》Mutex信号量构造
    【深度好文】多线程之WaitHandle-->派生-》Semaphore信号量构造
    开源框架 KJFrameForAndroid
  • 原文地址:https://www.cnblogs.com/jz929/p/13400085.html
Copyright © 2020-2023  润新知