UVA 11440 - Help Tomisu(数论好题)
题目链接 https://cn.vjudge.net/problem/UVA-11440
【题意】
输入整数 和 ,统计区间 之间有多少个整数 满足 的所有素因子都大于 答案对 取模
【思路】
首先 所以 是 的整数倍,而且 一个数的所有素因子都大于m 等价于 这个数和m!互素 ,而且根据gcd的性质,对于 与 互素等价于 和 互素. 这样一来,只要求出“不超过 且和 互素的数的个数” 再乘以 即可,关键就在于求出 设 根据欧拉函数公式
如果 不是素数,那么 和 的素因子集合完全相同,
如果 是素数,还会多一项 约分得
还要特别注意的情况
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod=100000007;
const int maxn=10000005;
int fac[maxn];
int invfac[maxn];
int phifac[maxn];
bool notprime[maxn];
int n,m;
void gcd(ll a,ll b,ll &d,ll& x,ll& y){
if (0==b){ d=a;x=1;y=0; }
else { gcd(b,a%b,d,y,x);y-=x*(a/b); }
}
ll inv(ll a,ll p){
ll d,x,y;
gcd(a,p,d,x,y);
return d==1?(x+p)%p:-1;
}
void init(){
notprime[0]=notprime[1]=true;
for(int i=2;i<maxn;++i){
if(!notprime[i]) for(int j=i*2;j<maxn;j+=i) notprime[j]=true;
}
fac[0]=fac[1]=1;
for(int i=2;i<maxn;++i) fac[i]=(ll)fac[i-1]*(ll)i%mod;
for(int i=0;i<maxn;++i) invfac[i]=inv(fac[i],mod);
phifac[1]=phifac[2]=1;
for(int i=3;i<maxn;++i){
phifac[i]=(ll)phifac[i-1]*(ll)(notprime[i]?i:i-1)%mod;
}
}
int main(){
init();
while(scanf("%d%d",&n,&m)==2){
if(0==n && 0==m) break;
int ans=phifac[m];
ans=(ll)ans*(ll)fac[n]%mod;
ans=(ll)ans*(ll)invfac[m]%mod;
printf("%d\n",(ans-1+mod)%mod);
}
return 0;
}