【2】ABC412E - LCM Sequence 解题报告
题意:给你一个区间 \([l,r]\),设 \(a_i\) 是 \(1\) 到 \(i\) 的最小公倍数的值。问当 \(l\leq i\leq r\) 时出现过多少个不同的 \(a_i\),数据范围满足 \(1\leq l,r\leq 10^{14},r-l\leq 10^7\)。
这题我主要通过对最小公倍数的变动次数,来统计答案。
对原有质因数范围的判定
对于这个题,我们自然想到对 \(a_l\) 分解质因数。注意到 \(> 10^7\) 的质因子需要再出现一次的话就需要一个 \(>10^{14}\) 的数,所以我们考虑所有质因子只考虑 \(\leq 10^7\) 的即可。
情况:出现原有的质因子
我们发现对于一个可能出现新次数的质因数 \(p\),设原先出现次数为 \(e\),那么我们要判断是否出现了 \(p^e\),\(p^{e+1}\),\(p^{e+2}\) 等更多的出现次数。我们注意到 \(e\ge 2\),那么枚举更多可能出现个数的复杂度就将会是 \(\mathcal O(\log_{e}r)\)。这是可以接受的。
具体的,我们枚举所有可能的数 \(p\),暴力计算是否 \(p^x\leq r\),其中 \(x\) 是一个从 \(e+1\) 开始不断往上枚举的数。当 \(p^x\) 有一个倍数是在 \([l,r]\) 之间的,那么我们就证明了会因为 \(p^x\) 导致数的变化,统计出这导致的变动次数。
情况:出现新的质因子
这个情况相当于 \([l,r]\) 之中出现了质数,那么我们要证明不会出现不存在的质因子。
证明:假设出现一个 \(10^7<p<l\),且 \(p^2\leq r\) 的质因子,落在 \([l,r]\) 里。那么我们就会发现,出现了 \(10^{14}\leq r\),不可能出现。
所以 \(p^2>r\),所以 \(l\leq p\leq r\) 就是一个质数。那么我们就可以想一个办法处理出 \(l<p\leq r\) 的质数。注意不能取到 \(l\),因为这个质数不会造成修改。我们想如何统计这个质数。注意我们有一个埃筛,是 \(\mathcal O(n\log \log n)\) 的(证明略),我们考虑将 \(r-l\leq 10^7\) 这个条件应用。我们发现因为我们可以求出 \(\leq 10^7\) 的所有质数,并且其他的质数 \(10^7<p\) 是不能用于筛去 \([l,r]\) 内的质数,所以我们可以只用 \(2\leq p\leq 10^7\) 的质数去筛出 \([l,r]\) 内的质数。这很有用,我们可以精确筛去 \([l,r]\) 内的合数,并且复杂度也是可以接受的。
总方法
那么到现在,我们统计了:
- 因为质因数次数增加导致的变动。
- 因为出现新的质数增加导致的变动。
这包含了所有的答案,注意出现数量要加上初始数量的 \(1\)。这样,我们就用不超过 \(\mathcal O(n\log n)\) 的复杂度解决问题,这里 \(n=r-l\)。我们应当可以在要求的时限内通过。
这里给出我的出错位置:
- 注意 \([l,r]\) 中取 \(p\) 倍数需要用好三目运算符,代码里的比较乱,大致就是 \(l\) 的下区间要向上取整,\(r\) 的上区间要向下取整,可以结合自己的写法。
- 注意极限可能会出现一个 \(10^7\times 10^{14}\) 的乘法,需要开好朋友
__int128。 - 再次强调枚举新质数范围不要包括 \(l\) 范围,原因见上文。不然你会因为只错一个点破防。
- 注意到问的是出现数量,这个数就是我们求出来的变动数量加上 \(1\)。
- 还有一个,我们不要乱用
map,可以加上一个偏移值 \(-l\) 来用数组来存储,不然直接给你卡超时高达 \(10000+\) 毫秒。
代码如下:
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=1e7+10;
int l,r,ans;
int gg(int x,int y){
if(!y)
return x;
return gg(y,x%y);
}
vector<int>Prime;
bool is[N];
int hh[N];
vector<pair<int,int> >l_lcm;
signed main(){
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin>>l>>r;
memset(is,1,sizeof(is));
is[0]=is[1]=0;
for(int i=2;i<=(int)1e7;i++)if(is[i]){
Prime.push_back(i);
for(int j=i+i;j<=(int)1e7;j+=i)is[j]=0;
for(int j=(l%i?(l/i+1)*i:l);j<=(r/i)*i;j+=i)if(j!=i)
hh[j-l]=1;
}
for(auto p:Prime){
if(p*p>r)
break;
int e=0;
__int128 mul=1;
while(mul*p<=l){
++e;
mul*=p;
}
l_lcm.push_back({p,e});
}
for(auto v:l_lcm){
int val=1;
if(v.second==0)
val*=v.first;
for(int i=1;i<=v.second;i++)
val=val*v.first;
__int128 mul=val;
while(mul*v.first<=r){
val=val*v.first;
int ll=(l%val?(l/val+1):l/val),rr=r/val;
ans+=bool(rr-ll+1);
mul*=v.first;
}
}
for(int j=l;j<=r;j++)
if(!hh[j-l]&&j>l)++ans;
cout<<ans+1;
return 0;
}
文章同步载入于洛谷,详见文章下方链接。
本文来自博客园,作者:Ivan422,转载请注明原文链接:https://www.cnblogs.com/Exfish/p/23270024。

浙公网安备 33010602011771号