BZOJ 2186: [Sdoi2008]沙拉公主的困惑 [欧拉函数][逆元]

来源:互联网 发布:rpc java 框架 编辑:程序博客网 时间:2024/04/24 18:47

题意:

给定n,m(nm),求[1,n!]m!互质的数的个数

解题报告:

分成两部分,第一部分是[1,m!),这部分的答案就是ϕ(m!)

第二部分是[m!,n!],我们知道有gcd(a,b)==gcd(a+b,b)

所以如果xm!互质,则x+m!im!也互质(x+m!in!)

所以这部分答案为ϕ(m!)(n!/m!),因为ϕ(x)=m!Π(pi1)/pi,(pix)

可以化为n!Π(pi1)/pi

然后处理一下素数的逆元直接算就好了,我比较蠢用筛法求出了所有的逆元,于是因为数组太大的问题WA了好久

#include<cstdio>#include<cmath>#include<ctime>#include<cstring>#include<iostream>#include<algorithm>#define LL long long#define N 10000000using namespace std;inline int read(){    int a=0;char f=1,c=getchar();    while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}    while(c>='0'&&c<='9'){a=a*10+c-'0';c=getchar();}    return a*f;}int n,m,T,R,cnt,fac[10000005],inv[10000005],prime[500005],f[10000005];bool mark[10000005];void Pre(){    fac[1]=1;for(int i=2;i<=N;++i) fac[i]=1ll*fac[i-1]*i%R;    inv[1]=1;    for(int i=2;i<=N;++i){        if(!mark[i]) prime[++cnt]=i;        for(int j=1;j<=cnt&&i*prime[j]<=N;++j){            mark[prime[j]*i]=1;            if(i%prime[j]==0) break;        }    }    for(int i=2;i<=N&&i<R;++i)        inv[i]=(R-1ll*R/i*inv[R%i]%R);    f[1]=1;    for(int i=2;i<=N;++i){        f[i]=f[i-1];        if(!mark[i]) f[i]=1ll*f[i]*(i-1)%R*inv[i%R]%R;    }}int main(){    T=read();R=read();    Pre();    while(T--){        n=read(),m=read();        printf("%d\n",1ll*fac[n]*f[m]%R);    }}
阅读全文
0 0