沙拉公主的困惑 bzoj-2186 Sdoi-2008

题目大意:求N!中与M!互质的数的个数。

注释:$1\le N,M\le 10^7$。

想法:显然是求$\phi(M!)$。这东西其实只需要将数据极限范围内所有的逆元崩出来就行了... ...

最后,附上丑陋的代码... ...

#include <stdio.h>
#define LL long long
int prim[5000001],n,m,t,p,env[10000001],fac[10000001],f[10000001],cnt;
bool vis[10000001];
int main()
{
    scanf("%d%d",&t,&p);
    env[1]=1;
    fac[0]=fac[1]=1;
    f[1]=1;
    for(int i=2;i<=10000000;i++)
    {
        if(i<=p)
            env[i]=(p-p/i)*1ll*env[p%i]%p;
        else
            env[i]=env[i-p];
        if(!vis[i])
        {
            if(env[i]%p!=0)
            f[i]=1ll*f[i-1]*env[i]%p*(i-1)%p;
            else
            {
                f[i]=1ll*f[i-1]*(i-1)%p;   
            }
            prim[cnt++]=i;
        }
        else f[i]=f[i-1];
        for(int j=0;j<cnt&&i*prim[j]<=10000000;j++)
        {
            vis[i*prim[j]]=1;
            if(i%prim[j]==0)break; 
        }
        if(i%p!=0)fac[i]=1ll*fac[i-1]*i%p;
        else
        {
            int num=i;
            while(num%p==0)num/=p;
            fac[i]=fac[i-1]*num%p; 
        }
    }
    while(t--)
    {
        scanf("%d%d",&n,&m);
        if(n>=p*2||(n>=p&&m<p))
        {printf("0\n");continue;}
        printf("%lld\n",1ll*f[m]*fac[n]%p);
    }
}

小结:数论真有趣