DZY Loves Math
Time Limit: 20 Sec Memory Limit: 512 MB
Submit: 485 Solved: 199
[Submit][Status][Discuss]
DZY Loves Math
Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 485 Solved: 199
[Submit][Status][Discuss]
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
7558588 9653114
6514903 4451211
7425644 1189442
6335198 4957
Sample Output
14225956593420
4332838845846
15400094813
HINT
【数据规模】
T<=10000
1<=a,b<=10^7
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3309
题目分析:参考巨巨博客
枚举d=gcd(i,j)得到
令g(x) = Σ[d|T]f(d)μ(T/d)
观察这个函数 由于含平方因子数的μ值都为零,因此我们只考虑μ(T/d)!=0的数
令T=p1^a1*p2^a2*...*pk^ak
d=p1^b1*p2^b2*...*pk^bk
如果存在ai≠aj(i≠j),那答案只取决于最大的幂,对于其余部分通过组合数的性质,取得的数字个数为奇数和偶数的数量相等,因此和都是0,故如果存在ai≠aj(i≠j),则g(T)=0
如果所有的a值都相等,我们假设对于任意选取方案,f值都不变,那么由于选取奇数个元素和偶数个元素的方案数相等,和仍然为0
但是有一种选取方案的f值=a-1 即d=p1*p2*p3*...pk时,因此要把那个减去,根据莫比乌斯函数性质,减去的是(-1)^k,因为是减去所以最终结果为(-1)^(k+1),故如果不存在ai≠aj,则g(T)=(-1)^(k+1)
#include <cstdio>
#include <cstring>
#include <algorithm>
#define ll long long
using namespace std;
int const MAX = 1e7 + 5;
//a表示最小素因子的幂,p_a表示最小素因子的乘积
int g[MAX], p[MAX], sum[MAX], a[MAX], p_a[MAX];
bool noprime[MAX];
void pre()
{
int pnum = 0;
for(int i = 2; i < MAX; i++)
{
if(!noprime[i])
{
p[pnum ++] = i;
g[i] = 1;
a[i] = 1;
p_a[i] = i;
}
for(int j = 0; i * p[j] < MAX; j++)
{
noprime[i * p[j]] = true;
if(i % p[j] == 0)
{
a[i * p[j]] = a[i] + 1;
p_a[i * p[j]] = p_a[i] * p[j];
if(i == p_a[i])
g[i * p[j]] = 1;
else
g[i * p[j]] = (a[i / p_a[i]] == a[i * p[j]] ? -g[i / p_a[i]] : 0);
break;
}
a[i * p[j]] = 1;
p_a[i * p[j]] = p[j];
g[i * p[j]] = (a[i] == 1 ? -g[i] : 0);
}
sum[i] = sum[i - 1] + g[i];
}
}
ll cal(int a, int b)
{
if(a > b)
swap(a, b);
ll ans = 0;
for(int i = 1, last = 0; i <= a; i = last + 1)
{
last = min(a / (a / i), b / (b / i));
ans += (ll) (a / i) * (b / i) * (sum[last] - sum[i - 1]);
}
return ans;
}
int main()
{
pre();
int T;
scanf("%d", &T);
while(T --)
{
int a, b;
scanf("%d %d", &a, &b);
printf("%lld\n", cal(a, b));
}
}