Description
对于正整数n,定义f(n)为n所含质因子的最大幂指数。例如f(1960)=f(2^3 * 5^1 * 7^2)=3, f(10007)=1, f(1)=0。
给定正整数a,b,求sigma(sigma(f(gcd(i,j)))) (i=1..a, j=1..b)。
Input
第一行一个数T,表示询问数。
接下来T行,每行两个数a,b,表示一个询问。
Output
对于每一个询问,输出一行一个非负整数作为回答。
Sample Input
4
7558588 9653114
6514903 4451211
7425644 1189442
6335198 4957
Sample Output
35793453939901
14225956593420
4332838845846
15400094813
HINT
【数据规模】
T<=10000
1<=a,b<=10^7
解题思路:
设 g(x)=∑d|xμ(d)f(xd) g ( x ) = ∑ d | x μ ( d ) f ( x d ) ,考虑如何快速求 g(x) g ( x )
首先
g(1)=0
g
(
1
)
=
0
,否则设
x=∏isptii,ti≤ti+1
x
=
∏
i
s
p
i
t
i
,
t
i
≤
t
i
+
1
,那么
若 t1<ts t 1 < t s ,则
否则 t1=t2=...=ts t 1 = t 2 = . . . = t s
这样就很好筛了,记录每个数最小质因数的幂数 t(x) t ( x ) 即除掉所有最小质因数后的数 last(x) l a s t ( x ) 即可。
时间复杂度为 O(n−Tn−−√) O ( n − T n )
#include<bits/stdc++.h>
#define ll long long
using namespace std;
int getint()
{
int i=0,f=1;char c;
for(c=getchar();(c!='-')&&(c<'0'||c>'9');c=getchar());
if(c=='-')c=getchar(),f=-1;
for(;c>='0'&&c<='9';c=getchar())i=(i<<3)+(i<<1)+c-'0';
return i*f;
}
const int N=10000005;
int pn,pri[N],t[N],last[N],g[N];
void sieve()
{
for(int i=2;i<N;i++)
{
if(!t[i])pri[++pn]=i,t[i]=last[i]=g[i]=1;
for(int j=1;j<=pn;j++)
{
ll k=i*pri[j];
if(k>=N)break;
if(i%pri[j]==0)
{
last[k]=last[i];
t[k]=t[i]+1;
if(last[k]==1)g[k]=1;
else g[k]=t[k]==t[last[k]]?-g[last[k]]:0;
break;
}
last[k]=i,t[k]=1,g[k]=(t[i]==1?-g[i]:0);
}
}
for(int i=2;i<N;i++)g[i]+=g[i-1];
}
ll F(int n,int m)
{
ll res=0;
if(n>m)swap(n,m);
for(int i=1,j;i<=n;i=j+1)
{
j=min(n/(n/i),m/(m/i));
res+=1ll*(n/i)*(m/i)*(g[j]-g[i-1]);
}
return res;
}
int main()
{
//freopen("lx.in","r",stdin);
sieve();
for(int T=getint();T;T--)
{
int n=getint(),m=getint();
printf("%lld\n",F(n,m));
}
return 0;
}