组合数学+逆元

http://oj.jxust.edu.cn/contest/Problem?id=1702&pid=6

题意:有n个人,现在有一个聚会,每个人都可以选择参加或者不参加。而参加的人中每个人要么只去送礼物,要么只接受礼物。不存在全部都接受礼物或者全部都送礼物的情况(这样要么没人送礼物,要么没人接受礼物了)。问有多少中情况?

输出:对结果mod1e9+7.

解法:ans=∑C(k,n)*(2^k-2)其中2<=k<=n

//#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include ;
#include 
#include 
#include 
#include 
#include 
#define ME(x , y) memset(x , y , sizeof(x))
#define SF(n) scanf("%d" , &n)
#define rep(i , n) for(int i = 0 ; i < n ; i ++)
#define INF  0x3f3f3f3f
#define PI acos(-1)
using namespace std;
typedef long long ll ;
const int mod = 1e9+7 ;

ll quickpow(ll x , ll y)
{
    ll ans = 1 ;
    while(y)
    {
        if(y & 1)
            ans = (ans * x) % mod ;
        y >>= 1 ;
        x = (x * x) % mod;
    }
    return ans % mod ;
}

int main()
{
    int n ;
    scanf("%d" , &n);
    if(n == 1)
    {
        cout << 1 << endl ;
        return 0 ;
    }
    if(n == 2)
    {
        cout << 2 << endl ;
        return 0 ;
    }

    ll x = n , y = 1 , ans = 0 ;
    for(int i = 2 ; i <= n ; i++)
    {
        x = (x * (n - i + 1))% mod , y = y * i % mod ;
        ans = (ans + x * quickpow(y , mod - 2)%mod * (quickpow(2 , i) - 2)) % mod;
    }
    cout << ans << endl ;

    return 0;
}

 求两数组

//#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include ;
#include 
#include 
#include 
#include 
#include 
#define ME(x , y) memset(x , y , sizeof(x))
#define SF(n) scanf("%d" , &n)
#define rep(i , n) for(int i = 0 ; i < n ; i ++)
#define INF  0x3f3f3f3f
#define PI acos(-1)
using namespace std;
typedef long long ll ;
const int mod = 1e9+7 ;
ll a[100009] , m[100009];

ll quickpow(ll x , ll y)
{
    ll ans = 1 ;
    while(y)
    {
        if(y & 1)
            ans = (ans * x) % mod ;
        y >>= 1 ;
        x = (x * x) % mod;
    }
    return ans % mod ;
}

int main()
{
    int n ;
    scanf("%d" , &n);
    if(n == 1)
    {
        cout << 1 << endl ;
        return 0 ;
    }
    if(n == 2)
    {
        cout << 2 << endl ;
        return 0 ;
    }
    a[1] = 1 , m[0] = 1 ;
    for(int i = 2 ; i <= n ; i++)
    {
        a[i] = a[i-1] * i % mod ;
    }
    m[n] = quickpow(a[n],mod-2);
    for(int i = n - 1 ; i >= 1 ; i--)//可以将逆元看成是倒数求解。
    {
        m[i] = m[i+1] * (i+1) % mod ;
    }
    ll ans = 0 ;
    for(int i = 2 ; i <= n ; i++)
    {
        ans += a[n]%mod * m[i]%mod * m[n-i]%mod * (quickpow(2 , i)-2)%mod;
        ans %= mod ;
    }
    cout << ans << endl;

    return 0;
}

你可能感兴趣的:(组合数学+逆元)