石头剪刀布---组合数取模,数论

https://oj.ismdeep.com/contest/Problem?id=1555&pid=1

题目描述

A和B在玩石头剪刀布的游戏(0代表石头,1代表剪刀,2代表布),他们进行了n场游戏,现在A知道B每场的情况,赢一场得一分,输和平不得分,问A最终得分为S的情况有多少种?

输入

第一行输入N和S,N表示进行N场游戏,S表示A的得分。(1NS105)

第二行输入N个数(0,1,2),表示B每场的情况。

输出

输出有多少中情况使的A得分为S,数字很大,需要对答案取模109+7

样例输入

3 1
0 1 2

样例输出

12

提示

费马小定理

题解:就是求C(n,s)*2n-s,难点在于组合数取模

#include<iostream>
#include<math.h>
#define max 0x3f3f3f3f
#define ll long long
#define mod 1000000007
using namespace std;
ll pow(ll a, ll b, ll m)
{
    ll ans = 1;
    a %= m;
    while(b)
    {
        if(b & 1)ans = (ans % m) * (a % m) % m;
        b /= 2;
        a = (a % m) * (a % m) % m;
    }
    ans %= m;
    return ans;
}
ll niyuan(ll x, ll p)//x关于p的逆元,p为素数
{
    return pow(x, p - 2, p);
}
ll C(ll n, ll m, ll p)//组合数C(n, m) % p
{
    if(m > n)
        return 0;
    ll up = 1, down = 1;//分子分母;
    for(int i = n - m + 1; i <= n; i++)
        up = up * i % p;
    for(int i = 1; i <= m; i++)
        down = down * i % p;
    return up * niyuan(down, p) % p;
}
ll Lucas(ll n, ll m, ll p)
{
    if(m == 0)
        return 1;
    return C(n % p, m % p, p) * Lucas(n / p, m / p, p) % p;
}
int main()
{
    ll n,s,x,temp;
    cin>>n>>s;
    for(ll i=0;i<n;i++)
        cin>>x;
    temp=Lucas(n,s,mod)*pow(2,n-s,mod);
    cout<<temp%mod<<endl;
    return 0;
}
原文地址:https://www.cnblogs.com/-citywall123/p/10673738.html