鏈接
先來看看求的是什麼東西
令表示數字在給定區間中出現了幾次,
換元,令
注意看
這玩意是個積性函數,對分析發現,
上式接着化簡
莫隊搞一搞
別以爲到這裏就結束了
卡常簡直把我給搞自閉了
必須寫的優美否則就會成狗
我的自閉過程:
代碼
#include <bits/stdc++.h>
#define maxn 100010
#define maxN 10000010
#define rep(_,__) for(_=1;_<=(__);_++)
#define sqr(x) ((x)*(x))
using namespace std;
typedef unsigned int uint;
typedef pair<uint,uint> pr;
uint prime[maxN/10], mu[maxN];
bool mark[maxN];
void shai(uint N)
{
uint i, j;
for(i=2;i<=N;i++)mark[i]=false;
*prime=0;
mu[1]=1;
for(i=2;i<=N;i++)
{
if(!mark[i])prime[++*prime]=i, mu[i]=-1;
for(j=1;j<=*prime and i*prime[j]<=N;j++)
{
mark[i*prime[j]]=true;
if(i%prime[j]==0)break;
mu[i*prime[j]]=-mu[i];
}
}
}
uint l[maxn], r[maxn], id[maxn], s[maxN], now, a[maxn], ans[maxn], S;
vector<pr> d[maxn];
void init()
{
uint i, j;
shai(10000000);
}
bool cmp(uint x, uint y)
{
if(l[x]/S==l[y]/S)return r[x]<r[y];
return l[x]/S < l[y]/S;
}
void upd(uint x, bool pos, vector<pr> &d)
{
for(auto T:d)
{
uint dlt = pos ? x/T.first : -(x/T.first);
now += T.second*dlt*((s[T.first]<<1)+dlt);
s[T.first] += dlt;
}
}
uint read(uint x=0)
{
uint c;
for(c=getchar();!isdigit(c);c=getchar());
for(;isdigit(c);c=getchar())x=x*10+c-0x30;
return x;
}
int main()
{
uint T, n, q, i, L, R, j;
init();
T=read();
while(T--)
{
n=read(), q=read();
S = sqrt(n);
rep(i,n)
{
a[i]=read();
d[i].clear();
for(j=1;j*j<=a[i];j++)
if(a[i]%j==0)
{
if(mu[j])
d[i].emplace_back(pr(j,j*mu[j]));
if(j!=a[i]/j and mu[a[i]/j])
d[i].emplace_back(pr(a[i]/j,a[i]/j*mu[a[i]/j]));
s[j]=s[a[i]/j]=0;
}
}
rep(i,q)
{
l[i]=read(), r[i]=read();
id[i]=i;
}
sort(id+1,id+q+1,cmp);
now = 0;
L=1, R=0;
rep(i,q)
{
for(;L<l[id[i]];L++)upd(a[L],false,d[L]);
for(;L>l[id[i]];L--)upd(a[L-1],true,d[L-1]);
for(;R>r[id[i]];R--)upd(a[R],false,d[R]);
for(;R<r[id[i]];R++)upd(a[R+1],true,d[R+1]);
ans[id[i]]=now;
}
rep(i,q)
{
printf("%u\n",ans[i]);
}
}
return 0;
}