星期四, 23. 二月 2017 05:10下午
SDOI 2008沙拉公主的困惑
题目大意
求1-N!中与M!互质的数的个数;
思路
∵
N>M
∴
N!
∣
M!
所以我们可以将N!分为
N!M!
段,那么这样的话,每段长度为M!
∵
p与q互质
∴
p+k仍然与q互质
那么 根据这个性质,就可以得到等式
sum=
N!M!
∗
=
N!M!
∗
M!
=N!
∗
先预处理出N!和 φ (M!)可以做到蜜汁O(1)出解;
#include <cstdio>
#include <algorithm>
#include <cmath>
#define max(a,b) a>b?a:b
using namespace std;
typedef long long LL;
const int MAXN = 10000000+50;
const int N = 10000+50;
int fac[MAXN],sum[MAXN],inv[MAXN],num;
int t,mod,A[N],B[N],maxn;
int prime1[MAXN];
bool prime[MAXN];
void Read(int &);
void init(int Maxn)
{
Maxn++;
sum[1]=1,fac[1]=1,inv[1]=1;
for(int i=2;i<Maxn;i++){
if(!prime[i])
prime1[++num]=i;
for(int j=1;j<=num && i*prime1[j]<Maxn;j++){
prime[i*prime1[j]]=1;
if(i%prime1[j]==0) break;
}
} //线性筛函数
for(int i=2;i<=Maxn;i++)
{
sum[i]=((LL)sum[i-1]*i%mod)%mod; //预处理阶乘
if(i<mod) inv[i]=(LL)(mod-mod/i)%mod*inv[mod%i]%mod;//预处理逆元
if(!prime[i]) fac[i]=(LL)fac[i-1]*(i-1)%mod*inv[i%mod]%mod;
else fac[i]=fac[i-1];
} //改成三个循环TLE3个点;
}
int main()
{
Read(t),Read(mod);
for(int i=1;i<=t;i++)
Read(A[i]),Read(B[i]),maxn=max(maxn,A[i]);
init(maxn);
for(int i=1;i<=t;i++)
printf("%lld\n",(LL)fac[B[i]]*sum[A[i]]%mod);
return 0;
}
void Read(int &in){
static char ch;
for(ch=getchar();ch>'9'||ch<'0';ch=getchar()) ;
for(in=0;ch>='0'&&ch<='9';ch=getchar()) in=in*10+ch-'0';
}