Gym - 101775A A - Chat Group 组合数+逆元

由题推出,需要求:

C(n,k) + C(n,k+1) +...+ C(n,n);

由于n巨大(1e9),而k 1e5;

可以转化为:  2^k - ( C(n,0) + C(n,1) + ... + C(n,k-1) )

C(n,k) = ( n*(n-1)*..(n-k+1) ) / ( k! );

恰好O(k)解决

因为涉及到分数取模,所以还要预处理   inv(k!) ,逆元打表见代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll maxn = 1e5 + 1;
const ll MOD = 1e9 + 7;

ll inv[maxn];

void init() {
    inv[1] = 1;
    for(int i = 2; i < maxn; ++i) {
        inv[i] = (MOD-(MOD/i))*inv[MOD%i] % MOD;
    }
}
ll quickPower(ll a, ll b) {
    ll ans = 1;
    while(b) {
        if(b&1) {
            ans = (ans*a)%MOD;
        }
        b >>= 1;
        a = (a*a) % MOD;
    }
    return ans;
}
int main() {
    // C(n,k) + C(n,k+1) +... + C(n, n);
    init();
    int T;
    scanf("%d", &T);
    for(int test = 1; test <= T; ++test) {
        ll n, k;
        scanf("%lld%lld", &n, &k);
        ll ans = quickPower(2,n)-1;
        ll t = n, sum = 0;
        for(ll i = 1; i < k; ) {
            sum = (sum + t) % MOD;
            t = (t*(n-i)%MOD*inv[++i]) % MOD;
        }
        ans = (ans + MOD - sum) % MOD;
        printf("Case #%d: %lld\n", test, ans);
    }

    return 0;
}

猜你喜欢

转载自blog.csdn.net/xiang_6/article/details/81159290