BZOJ 4830: [Hnoi2017]抛硬币

答案为 \(\sum \limits_{i=b+1}^{a+b}\binom{a+b}{i}\)
因为 \(\sum_{i=0}^k \binom{n}{k}=2^n\)
那么可以把上述式子拆成两部分求解
\(\sum \limits_{i=b+1}^{a+b}\binom{a+b}{i}=\sum\limits_{i=b+1}^{\lfloor \frac{a+b}{2} \rfloor}\binom{a+b}{i}+\sum\limits_{i=\lceil\frac{a+b}{2}\rceil}^{a+b}\binom{a+b}{i}\)
后半部分即为 \(2^{a+b-1}\)
前半部分扩展 Lucas 求解
因为模数的固定是 \(2^k5^k\) 的形式,可以先把模数设为 \(10^9\)
分别预处理出 \(2^9\)\(5^9\) 除去它们倍数的阶乘即可

#include <bits/stdc++.h>
#define pb push_back
#define fi first
#define se second
#define pii pair<int, int>
#define pli pair<ll, int>
#define SZ(x) ((int)(x).size())
#define lp p << 1
#define rp p << 1 | 1
#define mid ((l + r) / 2)
#define lowbit(i) ((i) & (-i))
typedef long long ll;
typedef unsigned long long ull;
typedef double db;
#define rep(i,a,b) for(int i=(a);i<(b);i++)
#define per(i,a,b) for(int i=((b)-1);i>=(a);i--)
#define Edg int ccnt=1,head[N],to[E],ne[E];void addd(int u,int v){to[++ccnt]=v;ne[ccnt]=head[u];head[u]=ccnt;}void add(int u,int v){addd(u,v);addd(v,u);}
#define Edgc int ccnt=1,head[N],to[E],ne[E],c[E];void addd(int u,int v,int w){to[++ccnt]=v;ne[ccnt]=head[u];c[ccnt]=w;head[u]=ccnt;}void add(int u,int v,int w){addd(u,v,w);addd(v,u,w);}
#define es(u,i,v) for(int i=head[u],v=to[i];i;i=ne[i],v=to[i])
const int INF=0x3f3f3f3f;
const ll inf=0x3f3f3f3f3f3f3f3f;
template<class T>T gcd(T a, T b) { while (b) { a %= b; std::swap(a, b); } return a; }
template<class T>bool chkmin(T &a, T b) { return a > b ? a = b, 1 : 0; }
template<class T>bool chkmax(T &a, T b) { return a < b ? a = b, 1 : 0; }
int qp(int a, ll b, int mod) {
	int ans = 1;
	while (b) {
		if (b & 1) ans = 1ll * a * ans % mod;
		b >>= 1;
		a = 1ll * a * a % mod;
	}
	return ans;
}

const int MOD = 1000000000;
void M(int &a) { if (a >= MOD) a -= MOD; if (a < 0) a += MOD; }
ll a, b;
int k;
const int N = 2e6 + 7;
int pre_2[N], pre_5[N], pmod2, pmod5;
template<class T>
T exgcd(T a, T b, T &x, T &y) {
	if (!b) { x = 1, y = 0; return a; }
	T g = exgcd(b, a % b, x, y);
	T temp = x;
	x = y;
	y = temp - a / b * y;
	return g;
}
template<class T>
void equ(T a, T b, T c, T &x, T &y) {
	T g = exgcd(a, b, x, y);
	if (c % g) {
		x = y = -INF;
		return;
	}
	a /= g, b /= g, c /= g;
	x = (x % b + b) % b;
	x = 1LL * x * c % b;
	y = b;
}
template<class T>
T inv(T a, T b) {
	T x, y;
	equ(a, b, 1, x, y);
	if (x == -INF) return -1;
	return x;
}
void init() {
	pre_2[0] = 1; pmod2 = qp(2, 9, MOD);
	rep (i, 1, pmod2 + 1) {
		pre_2[i] = pre_2[i - 1];
		if (i % 2) pre_2[i] = 1ll * i * pre_2[i - 1] % pmod2;
	}
	pre_5[0] = 1; pmod5 = qp(5, 9, MOD);
	rep (i, 1, pmod5 + 1) {
		pre_5[i] = pre_5[i - 1];
		if (i % 5) pre_5[i] = 1ll * i * pre_5[i - 1] % pmod5;
	}
}

ll count(ll n, int p) {
	ll ans = 0;
	for (ll i = n; i; i /= p)
		ans += i / p;
	return ans;
}

int fac(ll n, int p, int pt) {
	if (n == 0) return 1;
	int ans = 1;
	if (p == 2) ans = pre_2[pt] % pt;
	else ans = pre_5[pt] % pt;
	ans = qp(ans, n / pt, pt);
	if (p == 2) ans = 1ll * ans * pre_2[n % pt] % pt;
	else ans = 1ll * ans * pre_5[n % pt] % pt;
	ans = 1ll * ans * fac(n / p, p, pt) % pt;
	return ans;
}

int C(ll n, ll m, bool div2 = 0) {
	if (n < m) return 0;
	int ans = 0;
	{
		int p = 2, pt = pmod2;
		ll c = count(n, p) - count(m, p) - count(n - m, p);
		if (div2) c--;
		int temp = qp(p, c, pt);
		if (c < 9) {
			ll res = 1ll * fac(n, p, pt) * inv(fac(m, p, pt), pt) % pt * inv(fac(n - m, p, pt), pt) % pt * temp % pt;
			res = 1ll * res * (MOD / pt) * inv(MOD / pt, pt) % MOD;
			M(ans += res);
		}
	}
	{
		int p = 5, pt = pmod5;
		ll c = count(n, p) - count(m, p) - count(n - m, p);
		int temp = qp(p, c, pt);
		if (div2) temp = 1ll * temp * inv(2, pt) % pt;
		if (c < 9) {
			int res = 1ll * fac(n, p, pt) * inv(fac(m, p, pt), pt) % pt * inv(fac(n - m, p, pt), pt) % pt * temp % pt;
			res = 1ll * res * (MOD / pt) * inv(MOD / pt, pt) % MOD;
			M(ans += res);
		}
	}
	return ans % MOD;
}

void print(int ans) {
	if (k == 1) printf("%01d\n", ans);
	if (k == 2) printf("%02d\n", ans);
	if (k == 3) printf("%03d\n", ans);
	if (k == 4) printf("%04d\n", ans);
	if (k == 5) printf("%05d\n", ans);
	if (k == 6) printf("%06d\n", ans);
	if (k == 7) printf("%07d\n", ans);
	if (k == 8) printf("%08d\n", ans);
	if (k == 9) printf("%09d\n", ans);
}

signed main() {
#ifdef LOCAL
	freopen("ans.out", "w", stdout);
#endif
	init();
	while (~scanf("%lld%lld%d", &a, &b, &k)) {
		int ans = qp(2, a + b - 1, MOD);
		for (ll i = b + 1; i <= (a + b) / 2; i++)
			M(ans += C(a + b, i));
		if ((a + b) % 2 == 0) M(ans -= C(a + b, (a + b) / 2, 1));
		int pmod = 1;
		rep (i, 0, k) pmod *= 10;
		ans %= pmod;
		print(ans);
	}
#ifdef LOCAL
	printf("%.10f\n", (db)clock() / CLOCKS_PER_SEC);
#endif
	return 0;
}
posted @ 2020-03-12 15:42  Mrzdtz220  阅读(122)  评论(0编辑  收藏  举报