【题目链接】
【算法】
对问题稍加分析后,发现其实要求的就是 :
C(N,K) + C(N,K+1) + C(N,K+2) + ... + C(N,N)
因为N最大10^9,K最大10^5,很显然,我们不可能通过暴力或杨辉三角等来解决此题
我们发现 :
C(N,K) + C(N,K+1) + C(N,K+2) + ... + C(N,N)
= C(N,1) + C(N,2) + C(N,3) + ... + C(N,N) - C(N,1) - C(N,2) - ... - C(N,K-1)
= 2^N - 1 - C(N,1) - C(N,2) - ... - C(N,K-1)
同时,我们可以推出 : C(N,K) = C(N,K-1) * (N - K + 1) / K
我们可以通过这个递推式在O(K)的时间求出C(N,1)..C(N,K-1)
但是问题还没有完,由于这个式子要模10^9+7
因此在计算 C(N,K-1) * (N - K + 1) / K时,除法运算会变得十分棘手,我们怎么解决这个问题呢?
其实很简单,(a / b) mod P = (a * b的逆元)mod P,有了这个小结论,问题就迎刃而解了!
关于这个结论,具体的证明我就不给出了,详见这篇文章 :
http://blog.csdn.net/star_weeper/article/details/52973879
【代码】
#include<bits/stdc++.h> using namespace std; typedef long long ll; const ll MOD = 1e9 + 7; ll i,N,K,a=1,b=1,ans; template <typename T> inline void read(T &x) { ll f = 1; x = 0; char c = getchar(); for (; !isdigit(c); c = getchar()) { if (c == '-') f = -f; } for (; isdigit(c); c = getchar()) x = x * 10 + c - '0'; x *= f; } template <typename T> inline void write(T x) { if (x < 0) { putchar('-'); x = -x; } if (x > 9) write(x/10); putchar(x%10+'0'); } template <typename T> inline void writeln(T x) { write(x); puts(""); } inline ll pow_mod(ll a,ll n) { ll ans; if (!n) return 1; if (n == 1) return a; ans = pow_mod(a,n>>1); ans = ans * ans % MOD; if (n & 1) ans = ans * a % MOD; return ans; } inline void exgcd(ll a,ll b,ll &x,ll &y) { if (b == 0) { x = 1; y = 0; } else { exgcd(b,a%b,y,x); y -= a / b * x; } } inline ll inv(ll a) { ll x,y; exgcd(a,MOD,x,y); return (x % MOD + MOD) % MOD; } int main() { read(N); read(K); ans = pow_mod(2,N) - 1; for (i = 1; i < K; i++) { a = (a * i) % MOD; b = ((b % MOD) * ((N - i + 1) % MOD)) % MOD; ans = (ans - (b * inv(a)) % MOD) % MOD; if (ans < 0) ans += MOD; } writeln(ans); return 0; }