bzoj2186 莎拉公主的困惑【线性筛+欧拉函数+逆元】

来源:互联网 发布:js模块化开发 编辑:程序博客网 时间:2024/04/26 15:28

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2186

#include<iostream>#include<cstdio>#include<iomanip>#include<cstdlib>#include<cstring>#include<algorithm>#include<math.h>#include<ctype.h>#include<time.h>#include<stack>#include<queue>#include<bitset>#include<set>#include<map>#include<vector>#include<sstream>using namespace std;typedef long long ll;void fre(){freopen("in.txt","r",stdin);}#define MS(x,y) memset(x,y,sizeof(x))#define MC(x,y) memcpy(x,y,sizeof(x))#define zero(a) fabs(a)<eps#define equal(a,b) zero(a-b)const int pi=acos(-1);double e=2.718281828;const int N=1000000;int t,mod,n,m,cnt;int fac[N+5],ine[N+5],x[500005],ans[N+5];bool flag[N+5];void exgcd(int a,int b,int &x,int &y){    if(b==0)    {    x=1;    y=0;    return;    }    exgcd(b,a%b,x,y);    int t=x;x=y;y=t-a/b*y;}int getine(int t){    int x,y;    exgcd(t,mod,x,y);    return (x%mod+mod)%mod;}void init(){    fac[1]=1;    for(int i=2;i<=N;i++)        fac[i]=(ll)fac[i-1]*i%mod;    ine[1]=1;    for(int i=2;i<=N;i++)    {        if(!flag[i])            x[++cnt]=i,ine[i]=getine(i);        for(int j=1;x[j]*i<=N&&j<=cnt;j++)        {            flag[x[j]*i]=1;            //ine[pri[j]*i]=(ll)ine[pri[j]]*ine[i]%R;            if(i%x[j]==0)break;        }    }    ans[1]=1;    for(int i=2;i<=N;i++)    {        ans[i]=ans[i-1];        if(!flag[i])            ans[i]=(ll)ans[i]*(i-1)%mod*ine[i]%mod;    }}int main(){    scanf("%d%d",&t,&mod);    init();    while(t--)    {        scanf("%d%d",&n,&m);        printf("%I64d\n",(ll)fac[n]*ans[m]%mod);    }    return 0;}

分析:题目要求[1,n!]里与m!互质的数的个数,[1,m!]中与m!互质的数有Oular(m!)个,对于每个互质的

数,如果我们给他都加上M!,仍然和m!互质,即求Oular(m!)n!/m!, 根据欧拉函数的性质,可以把

Oular(m!)化简为m!((p1)/p),p为m!的质因数,就变成了求n!((p1)/p),求到此就很清晰了,

预处理线性筛出[1,10000000]的素数,求出逆元,同时求出阶乘取模,随便搞搞就出来了。

0 0
原创粉丝点击