石头剪刀布---组合数取模,数论
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的得分。(1≤N,S≤105)
第二行输入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; }
等风起的那一天,我已准备好一切