Topic description
In today's math class, Crash children learned the least common multiple (Least Common Multiple). For two positive integers a and b, LCM(a, b) represents the smallest positive integer that divides both a and b. For example, LCM(6, 8) = 24.
After returning home, Crash was still thinking about what he had learned in class. In order to study the least common multiple, he drew a table of N*M. A number is written in each grid, and the grid in the i-th row and the j-th column is written as LCM(i, j). A 4*5 form is as follows:
1 2 3 4 5
2 2 6 4 10
3 6 3 12 15
4 4 12 4 20
Looking at this table, Crash thought of a lot of questions to think about. But the problem he most wanted to solve was a very simple one: what is the sum of all the numbers in this table. When N and M are big, Crash can't do anything, so he finds a clever program to help him solve this problem. Since the final result can be very large, Crash just wants to know the sum of all the numbers in the table and the value of mod20101009.
Input and output format
Input format:
The first line of input contains two positive integers, representing N and M, respectively.
Output format:
output a positive integer representing the sum mod20101009 of all numbers in the table.
Input and output example
Input Sample #1: Copy
4 5
Output Sample #1: Copy
122
Description
30% of the data satisfy N, M≤ 10^3.
70% of the data satisfy N, M≤ 10^5.
100% of the data satisfy N, M≤ 10^7.
Analysis: There are some solutions in Luogu, which are quite detailed.
Note: The f[x] and g[x] set during inversion should set all the related terms with [gcd(i,j)==d], such as
f[x]=i*j in this question *[gcd(i,j)==d]
g[x]=i*j*[x|gcd(i,j)]
So f[x]=mul[x]*g[n/x]
finally knew how to ask for g under the guidance of dalao
Code:
#include <iostream>
#include <cstdio>
#include <cmath>
#define LL long long
const LL mod=20101009;
const LL maxn=10000007;
using namespace std;
LL ans;
LL not_prime[maxn],prime[maxn];
LL mul[maxn];
LL n,m,cnt;
void getmul(LL n)
{
mul[1]=1;
for (LL i=2;i<=n;i++)
{
if (!not_prime[i])
{
prime[++cnt]=i;
mul[i]=-1;
}
for (LL j=1;j<=cnt;j++)
{
if (i*prime[j]>n) break;
not_prime[i*prime[j]]=1;
if (i%prime[j]==0)
{
mul[i*prime[j]]=0;
break;
}
mul[i*prime[j]]=-mul[i];
}
}
for (LL i=1;i<=n;i++) mul[i]=(mul[i-1]+(mul[i]*i*i)%mod)%mod;
}
LL getsum(LL l,LL r)
{
return (l+r)*(r-l+1)%mod*10050505%mod;
}
LL g(int n,int m)
{
if (n>m) swap(n,m);
LL ans=0,last=0;
for (LL i=1;i<=n;i=last+1)
{
last=min(n/(n/i),m/(m/i));
ans=(ans+getsum(1,n/i)*getsum(1,m/i)%mod*(mul[last]-mul[i-1]+mod)%mod)%mod;
}
return ans;
}
int main()
{
getmul(maxn);
scanf("%lld%lld",&n,&m);
if (n>m) swap(n,m);
for (LL i=1,last=0;i<=n;i=last+1)
{
last=min(n/(n/i),m/(m/i));
ans=(ans+getsum(i,last)*g(n/i,m/i)%mod)%mod;
}
printf("%lld",ans);
}