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;
}

猜你喜欢

转载自www.cnblogs.com/Mrzdtz220/p/12469698.html
今日推荐