Description
对于正整数n,定义 f(n)f(n)f(n) 为 nnn 所含质因子的最大幂指数。例如
f(1960)=f(23∗51∗72)=3,f(10007)=1,f(1)=0f(1960)=f(2^3 * 5^1 * 7^2)=3, f(10007)=1, f(1)=0f(1960)=f(23∗51∗72)=3,f(10007)=1,f(1)=0。
给定正整数a,b,求∑i=1n∑j=1mf(gcd(i,j))\sum_{i=1}^{n}\sum_{j=1}^{m}f(gcd(i,j))∑i=1n∑j=1mf(gcd(i,j))。
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
分析:
推一波式子可得,
∑i=1n∑j=1mf(gcd(i,j))\sum_{i=1}^{n}\sum_{j=1}^{m}f(gcd(i,j))i=1∑nj=1∑mf(gcd(i,j))
∑D=1nf(D)∑i=1⌊nD⌋μ(d)∗⌊nDd⌋∗⌊mDd⌋\sum_{D=1}^{n}f(D)\sum_{i=1}^{\lfloor\frac{n}{D}\rfloor}\mu(d)*\lfloor\frac{n}{Dd}\rfloor*\lfloor\frac{m}{Dd}\rfloorD=1∑nf(D)i=1∑⌊Dn⌋μ(d)∗⌊Ddn⌋∗⌊Ddm⌋
∑T=1n⌊nT⌋⌊mT⌋∑d∣Tμ(d)∗f(Td)\sum_{T=1}^{n}\lfloor\frac{n}{T}\rfloor\lfloor\frac{m}{T}\rfloor\sum_{d|T}\mu(d)*f(\frac{T}{d})T=1∑n⌊Tn⌋⌊Tm⌋d∣T∑μ(d)∗f(dT)
现在就是求后面那个东西的前缀和。
设g(T)=∑d∣Tμ(d)∗f(Td)g(T)=\sum_{d|T}\mu(d)*f(\frac{T}{d})g(T)=∑d∣Tμ(d)∗f(dT),
因为要想μ(d)\mu(d)μ(d)不为000,满足
d=p1α1∗p2α2∗....∗pkαkd=p_1^{\alpha_1}*p_2^{\alpha_2}*....*p_k^{\alpha_k}d=p1α1∗p2α2∗....∗pkαk
其中αi=[0,1]\alpha_i=[0,1]αi=[0,1]。
考虑对于一个TTT,他的幂次只有减111或不变。也就是说,一开始最大的数,改变后还是最大的。
我们把αi\alpha_iαi分成两类,AAA为最大的数(包括和他一样的),BBB为不是最大的数。
组合数知识可以知道,在BBB中选出奇数个和偶数个的方案数是一样的,除非BBB为空集。
假设BBB不为空,此时无论AAA如何选,BBB中奇偶数一样,而贡献正好相反,所以总贡献为000。
如果BBB为空,说明AAA全是同一个数,除非全选最大值才会变。如果不变恰好为000,所以减了111贡献为
−(−1)k-(-1)^k−(−1)k,kkk为质数个数。
考虑怎样求这个东西。我们先找到所有无平方因子数,然后枚举他的幂,枚举幂其实复杂度是很小的,可以看做线性。
代码:
/**************************************************************
Problem: 3309
User: liangzihao
Language: C++
Result: Accepted
Time:17588 ms
Memory:313792 kb
****************************************************************/
#include <iostream>
#include <cstdio>
#include <cmath>
#define LL long long
const int maxn=1e7+7;
using namespace std;
LL T,a,b,n,m,ans,cnt;
LL prime[maxn],not_prime[maxn],mu[maxn],f[maxn];
void get(LL n)
{
mu[1]=1;
for (LL i=2;i<=n;i++)
{
if (!not_prime[i])
{
prime[++cnt]=i;
mu[i]=-1;
}
for (LL j=1;j<=cnt;j++)
{
if (prime[j]*i>n) break;
not_prime[i*prime[j]]=1;
if (i%prime[j]==0)
{
mu[i*prime[j]]=0;
break;
}
mu[i*prime[j]]=-mu[i];
}
}
f[1]=0;
for (LL i=2;i<=n;i++)
{
if (mu[i])
{
for (LL j=i;j<=n;j=j*i)
{
f[j]=-mu[i];
}
}
}
for (LL i=1;i<=n;i++) f[i]+=f[i-1];
}
int main()
{
scanf("%lld",&T);
get(1e7);
while (T--)
{
scanf("%lld%lld",&n,&m);
if (n>m) swap(n,m);
ans=0;
for (LL i=1,last;i<=n;i=last+1)
{
last=min(n/(n/i),m/(m/i));
ans+=(n/i)*(m/i)*(f[last]-f[i-1]);
}
printf("%lld\n",ans);
}
}