zoukankan      html  css  js  c++  java
  • luogu_2155 bzoj_2186【题解】沙拉公主的困惑

    题目:https://www.luogu.org/problemnew/show/P2155  (luogu)

       https://www.lydsy.com/JudgeOnline/problem.php?id=2186  (bzoj)

    这题要求在(1,N!)里与M!互质的数的个数。

    可以把问题分为两部分。

    第一部分就是用欧拉函数 phi( M! ) 求1到M!中与M!互质的数的个数。

    第二部分是M!+1到N!的与M!互质的个数。

    如果gcd( x+M! , M! )==1;那么肯定有gcd( x+M! , M! )==1 。

    所以,只用计算 N!到 M!有多少倍的( N! / M! )就可以算出。

    答案就为ansphi( M! ) * ( N! / M! ) % R

    但是如何求又是一个问题。

    化简式子:

    ans = ( N! / M!) * M! p|m[ (p-1) / p ]

    也就是ans = N!* ∏( p-1 ) / ∏ p 

    这时候可以用三个数组来预处理一下。

    fa[i] 存1到 i-1 的积。

    f1[i]=f1[ i-1 ]  (i是合数)

       =f1[ i-1 ] * ( i-1 )(i是质数)

    f2[i]=f2[ i-1 ](i是合数)

          =f2[ i-1 ] * i(i是质数)

    再用费马小定理求f2[ ]的乘法逆元。

    对于每对n,m,ans=fa[n] * f1[m] * { f2[m] ^ (p-2) }

    代码如下。

    /**************************************************************
        Problem: 2186
        User: ChrisK
        Language: C++
        Result: Accepted
        Time:6664 ms
        Memory:264964 kb
    ****************************************************************/
     
    #include<bits/stdc++.h>
    using namespace std;
    long long t,r,n,m;
    const int maxn=1e7+10;
    int prime[maxn>>1];// 开小一点。
    bool p[maxn];
    long long fa[maxn],f1[maxn],f2[maxn];
    inline long long qp(long long x,long long y){//快速幂
        long long re=1;
        while(y){
            if(y&1) re=(re*x)%r;
            x=(x*x)%r;
            y>>=1;
        }
        return re;
    }
    void prime3(){//线性求素数。
        int tot = 0;
        memset(p,true,sizeof(p));
        prime[0] = prime[1] = false;
        for(int i = 2;i <=maxn;i++){
            if(p[i])
                prime[++tot] = i;
            for(int j = 1;j <= tot && i * prime[j] <maxn;j++){
                p[i * prime[j]] = false;
                if(i % prime[j] == 0)
                    break;
            }
        }
    }
    int main()
    {
        scanf("%lld%lld",&t,&r);
        prime3();
        fa[1]=f1[1]=f2[1]=1;
        for(int i=2;i<=maxn;i++){
            fa[i]=(fa[i-1]*i)%r;
            if(p[i]){
                f1[i]=f1[i-1]*(i-1)%r;
                f2[i]=f2[i-1]*i % r;
            }
            else{
                f1[i]=f1[i-1];
                f2[i]=f2[i-1];
            }
        }
        while(t--){
            scanf("%lld%lld",&n,&m);
            printf("%lld
    ",(((fa[n]*f1[m])%r)*qp(f2[m],r-2)%r));
        }
    //  while(1);
        return 0;
    }
  • 相关阅读:
    一份感动到哭的成绩单……
    永远不要、不要、不要、不要放弃
    FusionChart 保存图片 小强斋
    JfreeChart的使用 小强斋
    JFreeChart中文API 小强斋
    FusionChart 小强斋
    面试题>旋转字符串 小强斋
    Dom4j 小强斋
    FusionChart 保存图片 小强斋
    JFreeChart中文API 小强斋
  • 原文地址:https://www.cnblogs.com/ChrisKKK/p/10883494.html
Copyright © 2011-2022 走看看