AtCoder Beginner Contest 156 D - Bouquet ——组合数学

D - Bouquet / 


Time Limit: 2 sec / Memory Limit: 1024 MB

Score : 400400 points

Problem Statement

Akari has nn kinds of flowers, one of each kind.

She is going to choose one or more of these flowers to make a bouquet.

However, she hates two numbers aa and bb, so the number of flowers in the bouquet cannot be aa or bb.

How many different bouquets are there that Akari can make?

Find the count modulo (109+7)(109+7).

Here, two bouquets are considered different when there is a flower that is used in one of the bouquets but not in the other bouquet.

Constraints

  • All values in input are integers.
  • 2≤n≤1092≤n≤109
  • 1≤a<b≤min(n,2×105) 

Input

Input is given from Standard Input in the following format:nn aa bb
​​​​​​ Output​

Print the number of bouquets that Akari can make, modulo (109+7)(109+7). (If there are no such bouquets, print 0.)


Sample Input 1 Copy

Copy

4 1 3

Sample Output 1 Copy

Copy

7

In this case, Akari can choose 22 or 44 flowers to make the bouquet.

There are 66 ways to choose 22 out of the 44 flowers, and 11 way to choose 44, so there are a total of 77 different bouquets that Akari can make.


Sample Input 2 Copy

Copy

1000000000 141421 173205

Sample Output 2 Copy

Copy

34076506

Print the count modulo (109+7)(109+7).

思路:

总的方案数就是C(n,1)+C(n,2)+ . . . . +C(n,n) = 2^{n}-1;然后不符合的方案数为C(n,a)+C(n,b);

两者相减就是答案;因为算组合数时,数据非常大,所以要用到lucas定理来计算组合数的大小;

需要注意的是,当同余定理用于减法的时候尽量在减完之后再加上模数,防止出现负数;

例如(6-3)% 6 = 3;

用同余定理计算后的(6%6-3%6)% 6 =(0-3)% 6 = -3;

当加上模数后 (6%6-3%6+6)% 6 =(0-3+6)% 6 = 3;

所以,还是加上好,不加这道题就过不了,我已经吃过很多次亏了;

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int p=1e9+7;
ll qmi(ll a, ll k)
{
    ll res = 1;
    while (k)
    {
        if (k & 1) res = (ll)res * a % p;
        a = (ll)a * a % p;
        k >>= 1;
    }
    return res;
}


ll C(int a, int b) 
{
    ll res = 1;
    for (ll i = 1, j = a; i <= b; i ++, j -- )
    {
        res = (ll)res * j % p;
        res = (ll)res * qmi(i, p - 2) % p;
    }
    return res;
}


ll lucas(ll a, ll b)
{
    if (a < p && b < p) return C(a, b);
    return (ll)C(a % p, b % p) * lucas(a / p, b / p) % p;
}
int main()
{
	ll n, a, b;
	cin >>n>>a>>b;
	cout <<(qmi(2,n)-(lucas(n,a)%p+lucas(n,b)%p)%p-1+p)%p<<endl;
}
发布了209 篇原创文章 · 获赞 40 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/weixin_43872728/article/details/104452320
今日推荐