zoukankan      html  css  js  c++  java
  • [题解]luogu_P2155_BZOJ_2186沙拉公主的困惑

    题意求1~N!中与M!互质的数的个数,

    首先证明gcd(a,b)=1时gcd(a-kb,b)=1

    gcd(a,b)=1

    gcd(a%b,b)=1

    gcd(a-kb,b)=1

    即a-kb与b互质

    这样由于n!一定是m!的倍数,所以如果把n!分成很多段m!的和:1~m!,m!~2m!......

    对于每一段的每个答案gcd(x,m!)=1时,也有gcd(x+km!,m!)=1

    所以每段的答案都是一样的

    这样答案变成了n!/m! * phi(m!)

    对于phi(m!)用计算公式展开:

    这里可以递推出相关的东西和逆元之类的,然而其实还可以继续简化运算

    其实也只是不用求逆元了而已吧

    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    #include<cstring>
    #define ll long long
    using namespace std;
    const int maxn=10000009;
    int n,m;
    ll mod;
    ll fac[maxn],f1[maxn],f2[maxn];
    int prime[maxn];
    bool ck[maxn];
    void init(){
        int tot=0;
        memset(ck,0,sizeof(ck));
        ck[0]=ck[1]=1;
        for(int i=2;i<=maxn;i++){
            if(!ck[i])prime[++tot]=i;
            for(int j=1;j<=tot;j++){
                if(i*prime[j]>maxn)break;
                ck[i*prime[j]]=1;
                if(i%prime[j]==0)break;
            }
        }
    }
    ll qpow(ll a,ll b){
        ll base=a,ans=1;
        while(b){
            if(b&1)ans=(ans*base)%mod;
            base=(base*base)%mod;
            b>>=1;
        }
        return ans%mod;
    }
    int main(){
        int T;
        scanf("%d%lld",&T,&mod);
        init();
        fac[1]=f1[1]=f2[1]=1ll;
        for(int i=2;i<maxn;i++){
            fac[i]=fac[i-1]*i%mod;
            if(!ck[i])
            f1[i]=f1[i-1]*(i-1)%mod,f2[i]=f2[i-1]*i%mod;
            else
            f1[i]=f1[i-1],f2[i]=f2[i-1];
        }
        while(T--){
            scanf("%d%d",&n,&m);
            printf("%lld
    ",((fac[n]*f1[m])%mod)*qpow(f2[m],mod-2)%mod);
        }
    }
  • 相关阅读:
    微软 面试题
    SQL 公用表表达式(CTE)
    SQL 事务(Transaction)
    arch中pacman的使用
    arch中yaourt的安装和使用
    今天安装了arch,感觉不错,这速度可以
    纠结于arch+xfce还是xubuntu
    ubuntu 提速
    【转】linux下杀死进程
    【转】debian下的update-rc.d的使用
  • 原文地址:https://www.cnblogs.com/superminivan/p/10875754.html
Copyright © 2011-2022 走看看