小红拿到了两个正整数 lll 和 rrr 。
她想知道 [l,r][l,r][l,r] 区间所有合数的最小公倍数是多少?由于答案可能过大,请对1000000007取模。
合数的定义:因子的个数不小于3的正整数。例如:9的因子有1、3、9这三个,所以9是合数。
输入描述:
两个正整数 lll 和 rrr ,用空格隔开。 数据范围:1≤l≤r≤300001\leq l \leq r \leq 300001≤l≤r≤30000
输出描述:
若区间 [l,r][l,r][l,r] 中没有任何合数,则输出-1。 否则输出区间 [l,r][l,r][l,r] 所有合数的最小公倍数,答案对1000000007取模。
示例1
输入
2 3
输出
-1
说明
区间 [2,3] 的两个数 2 和 3 都是素数,不是合数。
示例2
输入
4 6
输出
12
说明
区间[4,6]中有三个数:4、5、6,其中 5 是素数, 4 和 6 是合数,它们的最小公倍数是12。
示例3
输入
25000 30000
输出
187554966
思路:求最小公倍数其实就是求每个数的质数的幂的最大值,如:a=2^3 * 3 , b=2 * 3^3,最小公倍数就是:c=2^3 * 3^3。官方解释:区间所有合数的最小公倍数,也就是需要统计区间内每个素数出现的最高的幂。我们只需要统计出区间内的质数即可,计算它的最大幂,每个指数幂相乘即可。
完整代码:
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int mod=1e9+7;
const int N=3e4+10;
int prem[N];
bool st[N];
int a[N];
int qmi(int a,int x)
{
int res=1;
while(x)
{
if(x&1)res=res*a%mod;
a=a*a%mod;
x>>=1;
}
return res;
}
signed main() {
ios_base::sync_with_stdio(false);
cin.tie(NULL);
int l,r;
cin>>l>>r;
int idx=0;
st[1]=1;
for(int i=2;i<=r;i++)
{
if(!st[i])prem[++idx]=i;
for(int j=i+i;j<=r;j+=i)
{
st[j]=true;
}
}
bool ok=false;
for(int i=l;i<=r;i++)
{
if(!st[i])continue;
ok=true;
int pre=i;
for(int j=1;j<=idx;j++)
{
int num=1;
while(pre%prem[j]==0)pre/=prem[j],num=num*prem[j]%mod;
a[j]=max(a[j],num);
}
}
int ans=1;
for(int i=1;i<=idx;i++)
{
//ans=ans*qmi(prem[i],a[i])%mod;
ans=ans*a[i]%mod;
}
if(!ok)cout<<"-1"<<endl;
else cout<<ans<<endl;
return 0;
}