• [bzoj2186][Sdoi2008]沙拉公主的困惑


    来自FallDream的博客,未经允许,请勿转载,谢谢。


    题意:T组数据,每次求[1,n!]里有多少个与m!互质的数。  T<=10000 n,m<=10^7

    一开始想着乱容斥啥的 根本不可做...但是实际上没那么复杂。

    考虑把[1,n!]按照取余m!的不同分成m!组,发现要么全都互质,要么全都不互质,所以我们只要求[1,m!]里跟m!互质的数就好了,也就是求$varphi(m!)$

    那么这样就很简单了,根据欧拉函数的一套理论(#滑稽),我们先筛出质数,然后$varphi(m!)=m!*prod{frac{i-1}{i}}$,其中$1leqslant ileqslant m$且i是质数。

    答案就是$frac{n!}{m!}varphi(m!)$

    实现上还要线性求个逆元,这都很简单啦。

    然后考虑R<=m的情况,貌似出题人没有考虑到或者没有写出来,虽然不判断都能过,但是直接这么算是不行的。

    发现p在筛的时候会被除掉,所以在算阶乘的时候忽略它,然后在算的时候也不算它的逆元,可能就行了?

    貌似好麻烦,懒得实现了。

    #include<iostream>
    #include<cstdio>
    #define MN 10000000
    using namespace std;
    inline int read()
    {
        int x = 0 , f = 1; char ch = getchar();
        while(ch < '0' || ch > '9'){ if(ch == '-') f = -1;  ch = getchar();}
        while(ch >= '0' && ch <= '9'){x = x * 10 + ch - '0';ch = getchar();}
        return x * f;
    }
    
    int s[MN+5],T,mod,f[MN+5],num=0,inv[MN+5],p[MN+5];
    bool b[MN+5];
    
    int main()
    {
        T=read();mod=read();
        f[1]=1,p[0]=p[1]=inv[0]=inv[1]=1;
        for(register int i=2;i<=MN;++i)
        {
            if(!b[i]) s[++num]=i;
            for(int j=1;s[j]*i<=MN;++j)
            {
                b[s[j]*i]=1;
                if(i%s[j]==0) break;
            }
        }
        for(register int i=2;i<=MN;++i)
            p[i]=1LL*p[i-1]*i%mod,inv[i]=1LL*(mod-mod/i)*inv[mod%i]%mod;
        for(register int i=2;i<=MN;++i)
            f[i]=(b[i]?f[i-1]:(1LL*f[i-1]*(i-1)%mod*inv[i]%mod));
        for(register int i=1;i<=T;++i)
        {
            int n=read(),m=read();
            printf("%d
    ",1LL*p[n]*f[m]%mod);
        }
        return 0;
    }
  • 相关阅读:
    NET网络配置
    NTP时间同步器
    NFS配置linux
    DNS配置域名解析
    ftp配置windows
    samba配置与windows
    NTP服务和DNS服务
    NFS服务和DHCP服务scp
    SAMBA服务和FTP服务
    find用法
  • 原文地址:https://www.cnblogs.com/FallDream/p/bzoj2186.html
Copyright © 2020-2023  润新知