取石子(快速幂,逆元)

链接: 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;
} 

猜你喜欢

转载自blog.csdn.net/soul_97/article/details/80465811