您的位置:首页 > 其它

【SDOI2008】【BZOJ2186】沙拉公主的困惑

2016-08-14 23:00 369 查看

Description

 大富翁国因为通货膨胀,以及假钞泛滥,政府决定推出一项新的政策:现有钞票编号范围为1到N的阶乘,但是,政府只发行编号与M!互质的钞票。房地产第一大户沙拉公主决定预测一下大富翁国现在所有真钞票的数量。现在,请你帮助沙拉公主解决这个问题,由于可能张数非常大,你只需计算出对R取模后的答案即可。R是一个质数。

Solution

很显然,比m!小的与m!互质的个数,当他们* 2,* 3,*……时,可以倍增出更多的数,与m!互质的数的个数是φ(m!)个。

ans=φ(m!)∗n!m!

ans=m!∗n!m!∗所有质数p|m!(p−1p)的乘积

ans=n!∗所有质数p|m!(p−1p)的乘积

这些线筛就好了。

逆元用快速幂或扩展欧几里得就能过。

不过可以线性求逆元

Code

#include<iostream>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define fo(i,a,b) for(i=a;i<=b;i++)
using namespace std;
const int maxn=10000007;
typedef long long ll;
int i,j,k,l,t,n,m;
ll ans1;
int fact[maxn],ni[maxn],ans[maxn];
int p[maxn],cas,mo;
bool bz[maxn];
int main(){
scanf("%d%d",&cas,&mo);
fact[0]=fact[1]=1;ni[1]=1;
fo(i,2,10000000){
fact[i]=(ll)fact[i-1]*i%mo;
ni[i]=(ll)(mo-mo/i)*ni[mo%i]%mo;
if(!bz[i]){
p[++p[0]]=i;
}
fo(j,1,p[0]){
t=p[j]*i;
if(t>10000000)break;
bz[t]=1;
if(!(i%p[j]))break;
}
}
ans[1]=1;
fo(i,2,10000000){
if(bz[i])ans[i]=ans[i-1];
else ans[i]=(ll)ans[i-1]*(i-1)%mo*ni[i]%mo;
}
while(cas--){
scanf("%d%d",&n,&m);
ans1=(ll)fact
*ans[m]%mo;
printf("%lld\n",ans1);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: