取石子(快速冪,逆元)
阿新 • • 發佈:2019-01-21
連結:https://www.nowcoder.com/acm/contest/113/A
來源:牛客網
來源:牛客網
題目描述
給出四堆石子,石子數分別為a,b,c,d。規定每次只能從堆頂取走石子,問取走所有石子的方案數。輸入描述:
在一行內讀入四個由空格分隔的整數a,b,c,d, 輸入均為不超過500的正整數
輸出描述:
輸出一個整數表示答案,答案對109+7取模
翻譯過來就是有4個隊的人 人數可能不同 站成一個大隊伍一共用多少種排列方式
四堆石子看作4隊人 4個隊的人排成一排的方案數量 首先總人數全排列,然後去重
因為每個隊伍裡面的人看作是一樣的無區別的
費馬小定理
在模為素數p的情況下,有費馬小定理
a^(p-1)=1(mod p)
那麼a^(p-2)=a^-1(mod p)
也就是說a的逆元為a^(p-2)
而在模不為素數p的情況下,有尤拉定理
a^phi(m)=1(mod m) (a⊥m)
同理a^-1=a^(phi(m)-1)
因此逆元x便可以套用快速冪求得了x=a^(phi(m)-1)
#include <bits/stdc++.h> using namespace std; #define fi first #define se second #define pb push_back #define mset(a,b) memset(a,b,sizeof(a)) #define sz size() #define cl clear() #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define PI 3.1415926535897932384626433832795028841971693993751058209749445923078164 typedef long long ll; typedef pair<int,int> pr; const int inf = 99999999; const double eps = 1e-8; const int dir4[4][2] = {{-1,0},{1,0},{0,-1},{0,1}}; const int dir8[8][2] = {{1,0},{-1,0},{0,1},{0,-1},{1,1},{1,-1},{-1,1},{-1,-1}}; const int mon[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; const int monn[] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; const int mod = 1e9 + 7; //快速冪 ll quickPow(ll a,ll b) { ll res = 1; while(b) { if(b & 1) { res = res * a % mod; } a = a * a % mod; b >>= 1; } return res; } ll inv(ll x) { ll res = 1; res = quickPow(x,mod-2) % mod; return res; } ll jc(ll a) { ll res = 1; for(int i = 1;i <= a;i ++) res = res * i % mod; return res; } int main() { ll a, b, c, d; cin >> a >> b >> c >> d; ll sum = jc(a+b+c+d); cout << sum * inv(jc(a))% mod* inv(jc(b))% mod * inv(jc(c)) % mod* inv(jc(d)) % mod; return 0; }