单点时限: 3.0 sec
内存限制: 512 MB
Steve参加了2019年的暑期集训,在集训最后一场积分赛时,Steve英勇AC,提交了几十发全A了。Steve顿时惊叹,这不都是水题吗,于是接下来碰到的问题却难倒了他。求1n! 模p意义下的值。
输入格式
多组输入,处理到文件结束。
每行输入两个数n,p,(1≤n≤105,n<p≤109).
数据保证 p 是个质数。
输出格式
如题
样例
input
3 5 3 7 3 11
output
1 6 2
题解:
一开始我的思路是先求阶乘,求出来后再求阶乘的逆元,错了。
错误的原因是先求了阶乘,阶乘一般很大的。下面是前16的阶乘,直接就爆long long了。
所以就在求阶乘的过程中取余,这样就不会爆long long了。
AC代码:
#include <iostream>
#include <algorithm>
#include <cstdio>
using namespace std;
typedef long long ll;
ll exgcd(ll a,ll b,ll &x,ll &y)
{
if(b==0)
{
x=1,y=0;
return a;
}
ll r=exgcd(b,a%b,x,y);
ll tmp=y;
y=x-(a/b)*y;
x=tmp;
return r;
}
int main()
{
// freopen("input.txt","r",stdin); //提交时关闭
std::ios::sync_with_stdio(false);
ll n,p;
while(cin>>n>>p){
ll sum=1;
for(int i=1;i<=n;i++)
{
sum=sum*i%p;//注意这里右边必须有sum,如果是sum=i%p的话,相当于没取余了,目的是对部分阶乘后的阶乘取余,在每一个阶段不让它爆longlong
}
ll x,y;
exgcd(sum,p,x,y);
cout<<(x+p)%p<<endl;}
return 0;
}