【题目链接】
【算法】
对问题稍加分析后,发现其实要求的就是 :
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;
}