首页 > 代码库 > BZOJ 2186 沙拉公主的困惑(预处理逆元+欧拉函数)

BZOJ 2186 沙拉公主的困惑(预处理逆元+欧拉函数)

题意:求1-n!里与m!互质的数有多少?(m<=n<=1e6).

因为n!%m!=0,所以题目实际上求的是phi(m!)*n!/m!.

技术分享

预处理出这些素数的逆元和阶乘的模即可。

技术分享
# include <cstdio>
# include <cstring>
# include <cstdlib>
# include <iostream>
# include <vector>
# include <queue>
# include <stack>
# include <map>
# include <bitset>
# include <set>
# include <cmath>
# include <algorithm>
using namespace std;
# define lowbit(x) ((x)&(-x))
# define pi acos(-1.0)
# define eps 1e-8
# define MOD 30031
# define INF 1000000000
# define mem(a,b) memset(a,b,sizeof(a))
# define FOR(i,a,n) for(int i=a; i<=n; ++i)
# define FO(i,a,n) for(int i=a; i<n; ++i)
# define bug puts("H");
# define lch p<<1,l,mid
# define rch p<<1|1,mid+1,r
# define mp make_pair
# define pb push_back
typedef pair<int,int> PII;
typedef vector<int> VI;
# pragma comment(linker, "/STACK:1024000000,1024000000")
typedef long long LL;
int Scan() {
    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;
}
const int N=10000005;
//Code begin...

int fac[N], pri[N], inv[N], ans[N];
bool vis[N];
int P, tot;
void init(int n)
{
    fac[1]=1;
    FOR(i,2,n) fac[i]=(LL)fac[i-1]*i%P;
    inv[1]=1;
    FOR(i,2,n){
        if(!vis[i])pri[++tot]=i;
        for(int j=1; pri[j]*i<=n&&j<=tot; ++j){
            vis[pri[j]*i]=1;
            if(i%pri[j]==0) break;
        }
    }
    for(int i=2; i<=n&&i<P; ++i) inv[i]=(P-(LL)P/i*inv[P%i]%P);
    ans[1]=1;
    FOR(i,2,n) {
        ans[i]=ans[i-1];
        if(!vis[i])ans[i]=(LL)ans[i]*(i-1)%P*inv[i%P]%P;
    }
}
int main()
{
    int T, n, m; scanf("%d%d",&T,&P); init(N-5);
    while(T--){
        scanf("%d%d",&n,&m);
        printf("%d\n",(LL)fac[n]*ans[m]%P);
    }
    return 0;
}
View Code

 

BZOJ 2186 沙拉公主的困惑(预处理逆元+欧拉函数)