题目大意
有一个长度为
n
的序列
∑i=lr∑j=lrω(gcd(Ai,Aj))
其中 ω(x) 为 x 的不同质因子个数。
题目分析
对每一个质因子分开来考虑,如果一个质因子出现在这个区间的
x
个数中,那么其贡献就是
代码实现
#include <algorithm>
#include <iostream>
#include <cstdio>
#include <cctype>
#include <cmath>
using namespace std;
typedef long long LL;
int read()
{
int x=0,f=1;
char ch=getchar();
while (!isdigit(ch)) f=ch=='-'?-1:f,ch=getchar();
while (isdigit(ch)) x=x*10+ch-'0',ch=getchar();
return x*f;
}
int buf[30];
void write(LL x)
{
if (x<0) putchar('-'),x=-x;
for (;x;x/=10) buf[++buf[0]]=x%10;
if (!buf[0]) buf[++buf[0]]=0;
for (;buf[0];putchar('0'+buf[buf[0]--]));
}
LL sqr(int x){return 1ll*x*x;}
const int A=10000000;
const int N=100050;
const int Q=100050;
struct query
{
int l,r,id;
}qy[Q+5];
int pri[A+5],f[A+5],g[A+5],cnt[A+5];
int n,q,bs,lcur,rcur;
LL ans[N];
int a[N];
LL cur;
bool operator<(query a,query b){return (a.l-1)/bs<(b.l-1)/bs||(a.l-1)/bs==(b.l-1)/bs&&a.r<b.r;}
void pre()
{
f[1]=g[1]=1;
for (int i=2;i<=A;++i)
{
if (!f[i]) pri[++pri[0]]=f[i]=g[i]=i;
for (int j=1,x;j<=pri[0];++j)
{
if (1ll*pri[j]*i>A) break;
f[x=pri[j]*i]=pri[j];
g[x]=(f[i]==f[x]?g[i]:1)*pri[j];
if (!(i%pri[j])) break;
}
}
}
void add(int id){for (int x=a[id];x!=1;x/=g[x]) cur-=sqr(cnt[f[x]]),cur+=sqr(++cnt[f[x]]);}
void erase(int id){for (int x=a[id];x!=1;x/=g[x]) cur-=sqr(cnt[f[x]]),cur+=sqr(--cnt[f[x]]);}
void Mo_Algorithm()
{
cur=0;
for (lcur=qy[1].l,rcur=lcur-1;rcur<qy[1].r;add(++rcur));
ans[qy[1].id]=cur;
for (int i=2;i<=q;++i)
{
for (;lcur<qy[i].l;erase(lcur++));
for (;lcur>qy[i].l;add(--lcur));
for (;rcur<qy[i].r;add(++rcur));
for (;rcur>qy[i].r;erase(rcur--));
ans[qy[i].id]=cur;
}
}
int main()
{
pre();
freopen("sequence.in","r",stdin),freopen("sequence.out","w",stdout);
n=read(),q=read();
for (int i=1;i<=n;++i) a[i]=read();
for (int i=1;i<=q;++i) qy[i].l=read(),qy[i].r=read(),qy[i].id=i;
bs=trunc(sqrt(n)+1),sort(qy+1,qy+1+q);
Mo_Algorithm();
for (int i=1;i<=q;++i) write(ans[i]),putchar('\n');
fclose(stdin),fclose(stdout);
return 0;
}