题目传送门
题意:在一个 n ∗ m n*m n∗m的矩阵上,将每个点和点 ( 0 , 0 ) (0,0) (0,0)连起来,假设线段上除了两端点有 k k k个点,这个点的贡献是 2 ∗ k + 1 2*k+1 2∗k+1,求这 n ∗ m n*m n∗m个点的贡献和。
思路:可以知道,假设有点
(
i
,
j
)
(i,j)
(i,j),
(
i
,
j
)
(i,j)
(i,j)的贡献是
2
∗
g
c
d
(
i
,
j
)
−
1
2*gcd(i,j)-1
2∗gcd(i,j)−1。那么答案显而易见:
a
n
s
=
∑
i
=
1
n
∑
j
=
1
m
(
2
∗
g
c
d
(
i
,
j
)
−
1
)
=
2
∗
∑
i
=
1
n
∑
j
=
1
m
(
g
c
d
(
i
,
j
)
)
−
n
∗
m
=
2
∗
∑
g
=
1
m
i
n
(
n
,
m
)
g
∗
∑
i
=
1
n
∑
j
=
1
m
[
g
c
d
(
i
,
j
)
=
g
]
−
n
∗
m
\begin{aligned}\\ ans&=\sum\limits_{i=1}^{n}\sum\limits_{j=1}^{m}(2*gcd(i,j)-1)\\ &=2*\sum\limits_{i=1}^{n}\sum\limits_{j=1}^{m}(gcd(i,j))-n*m\\ &=2*\sum\limits_{g=1}^{min(n,m)}g*\sum\limits_{i=1}^{n}\sum\limits_{j=1}^{m}[gcd(i,j)=g]-n*m \end{aligned}
ans=i=1∑nj=1∑m(2∗gcd(i,j)−1)=2∗i=1∑nj=1∑m(gcd(i,j))−n∗m=2∗g=1∑min(n,m)g∗i=1∑nj=1∑m[gcd(i,j)=g]−n∗m
然后上面这个式子就可以 O ( n n ) O(n\sqrt n) O(nn )求了。
C o d e Code Code
// Author : ACfunhsl
// Time : 2021/5/17 14:13:11
#define int long long
const int N = 1e5+50;
const int inf = 0x3f3f3f3f;
const int mod = 1e9+7;
bool ok[N];
int p[N],cnt=0,mu[N];
void euler()
{
mu[1] = 1;
for(int i=2;i<N;i++)
{
if(!ok[i])
{
p[++cnt] = i;
mu[i] = -1;
}
for(int j=1;j<=cnt&&i*p[j]<N;j++)
{
ok[i*p[j]] = 1;
if(i%p[j]==0)
{
mu[i*p[j]] = 0;
break;
}
else mu[i*p[j]] = -mu[i];
}
}
for(int i=1;i<N;i++)
mu[i] += mu[i-1];
}
int k;
int cal(int n,int m)
{
n/=k;m/=k;
int mi = min(n,m),res = 0;
for(int l=1,r;l<=mi;l=r+1)
{
r = min(n/(n/l),(m/(m/l)));
res += (n/l)*(m/l)*(mu[r] - mu[l-1]);
}
return res;
}
signed main()
{
euler();
int n,m;
cin>>n>>m;
int res = 0;
for(int i=1;i<=min(n,m);i++)
{
k = i;
res += cal(n,m) * k;
}
res = res * 2 - n*m;
cout<<res<<endl;
return 0;
}