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\n",(((fa[n]*f1[m])%r)*qp(f2[m],r-2)%r));
    }
//  while(1);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/ChrisKKK/p/10883494.html