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

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

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

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

# 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-
# define MOD
# define INF
# 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<<,l,mid
# define rch p<<|,mid+,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=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<=''){x=x*+ch-'';ch=getchar();}
return x*f;
}
const int N=;
//Code begin... int fac[N], pri[N], inv[N], ans[N];
bool vis[N];
int P, tot;
void init(int n)
{
fac[]=;
FOR(i,,n) fac[i]=(LL)fac[i-]*i%P;
inv[]=;
FOR(i,,n){
if(!vis[i])pri[++tot]=i;
for(int j=; pri[j]*i<=n&&j<=tot; ++j){
vis[pri[j]*i]=;
if(i%pri[j]==) break;
}
}
for(int i=; i<=n&&i<P; ++i) inv[i]=(P-(LL)P/i*inv[P%i]%P);
ans[]=;
FOR(i,,n) {
ans[i]=ans[i-];
if(!vis[i])ans[i]=(LL)ans[i]*(i-)%P*inv[i%P]%P;
}
}
int main()
{
int T, n, m; scanf("%d%d",&T,&P); init(N-);
while(T--){
scanf("%d%d",&n,&m);
printf("%d\n",(LL)fac[n]*ans[m]%P);
}
return ;
}
05-11 22:56