题目描述
T
T
T组数据,给出
N
N
N,
M
M
M,求
∑
x
=
1
N
∑
y
=
1
M
l
i
m
(
x
,
y
)
\sum_{x=1}^N\sum_{y=1}^M lim(x,y)\newline
x=1∑Ny=1∑Mlim(x,y)
N
,
M
<
=
10000000
T
<
=
10000
N,M <= 10000000\newline T<= 10000
N,M<=10000000T<=10000
题目分析
直接开始变换,假设N<M
A
n
s
=
∑
x
=
1
N
∑
y
=
1
M
x
y
(
x
,
y
)
=
∑
T
=
1
N
1
T
∑
x
=
1
N
∑
y
=
1
M
x
y
[
(
x
,
y
)
=
=
T
]
=
∑
T
=
1
N
1
T
∑
x
=
1
⌊
N
T
⌋
∑
y
=
1
⌊
M
T
⌋
x
y
T
2
[
(
x
,
y
)
=
=
1
]
=
∑
T
=
1
N
T
∑
x
=
1
⌊
N
T
⌋
∑
y
=
1
⌊
M
T
⌋
x
y
∑
d
∣
x
,
d
∣
y
μ
(
d
)
=
∑
d
=
1
N
μ
(
d
)
∑
T
=
1
N
T
∑
d
∣
x
⌊
N
T
⌋
x
∑
d
∣
y
⌊
M
T
⌋
y
=
∑
d
=
1
N
μ
(
d
)
∑
T
=
1
N
T
d
2
∑
x
=
1
⌊
⌊
N
T
⌋
d
⌋
x
∑
y
=
1
⌊
⌊
M
T
⌋
d
⌋
y
=
∑
d
=
1
N
μ
(
d
)
∑
T
=
1
N
T
d
2
∑
x
=
1
⌊
N
T
d
⌋
x
∑
y
=
1
⌊
M
T
d
⌋
y
此
时
令
k
=
T
d
A
n
s
=
∑
k
=
1
N
∑
T
∣
k
μ
(
⌊
k
T
⌋
)
k
⌊
k
T
⌋
∑
x
=
1
⌊
N
k
⌋
x
∑
y
=
1
⌊
M
k
⌋
y
=
∑
k
=
1
N
k
∑
T
∣
k
μ
(
T
)
T
∑
x
=
1
⌊
N
k
⌋
x
∑
y
=
1
⌊
M
k
⌋
y
Ans=\sum_{x=1}^N\sum_{y=1}^M \frac {xy}{(x,y)}\newline =\sum_{T=1}^N\frac 1T\sum_{x=1}^N\sum_{y=1}^Mxy[(x,y)==T]\newline =\sum_{T=1}^N\frac 1T\sum_{x=1}^{⌊\frac NT⌋}\sum_{y=1}^{⌊\frac MT⌋}xyT^2[(x,y)==1]\newline =\sum_{T=1}^NT\sum_{x=1}^{⌊\frac NT⌋}\sum_{y=1}^{⌊\frac MT⌋}xy\sum_{d|x,d|y}\mu(d)\newline =\sum_{d=1}^N\mu(d)\sum_{T=1}^{N}T\sum_{d|x}^{⌊\frac NT⌋}x\sum_{d|y}^{⌊\frac MT⌋}y\newline =\sum_{d=1}^N\mu(d)\sum_{T=1}^{N}Td^2\sum_{x=1}^{⌊\frac{⌊\frac NT⌋}d⌋}x\sum_{y=1}^{⌊\frac{⌊\frac MT⌋}d⌋}y\newline =\sum_{d=1}^N\mu(d)\sum_{T=1}^{N}Td^2\sum_{x=1}^{⌊\frac N{Td}⌋}x\sum_{y=1}^{⌊\frac M{Td}⌋}y\newline 此时令k=Td\newline Ans=\sum_{k=1}^N\sum_{T|k}\mu(⌊\frac kT⌋)k⌊\frac kT⌋\sum_{x=1}^{⌊\frac N{k}⌋}x\sum_{y=1}^{⌊\frac M{k}⌋}y\newline =\sum_{k=1}^Nk\sum_{T|k}\mu(T)T\sum_{x=1}^{⌊\frac N{k}⌋}x\sum_{y=1}^{⌊\frac M{k}⌋}y\newline
Ans=x=1∑Ny=1∑M(x,y)xy=T=1∑NT1x=1∑Ny=1∑Mxy[(x,y)==T]=T=1∑NT1x=1∑⌊TN⌋y=1∑⌊TM⌋xyT2[(x,y)==1]=T=1∑NTx=1∑⌊TN⌋y=1∑⌊TM⌋xyd∣x,d∣y∑μ(d)=d=1∑Nμ(d)T=1∑NTd∣x∑⌊TN⌋xd∣y∑⌊TM⌋y=d=1∑Nμ(d)T=1∑NTd2x=1∑⌊d⌊TN⌋⌋xy=1∑⌊d⌊TM⌋⌋y=d=1∑Nμ(d)T=1∑NTd2x=1∑⌊TdN⌋xy=1∑⌊TdM⌋y此时令k=TdAns=k=1∑NT∣k∑μ(⌊Tk⌋)k⌊Tk⌋x=1∑⌊kN⌋xy=1∑⌊kM⌋y=k=1∑NkT∣k∑μ(T)Tx=1∑⌊kN⌋xy=1∑⌊kM⌋y
总算推完了…
此时只需要
Θ
(
N
)
\Theta(N)
Θ(N)线性筛出
∑
T
∣
k
μ
(
T
)
T
\sum_{T|k}\mu(T)T
∑T∣kμ(T)T,然后处理
k
∑
T
∣
k
μ
(
T
)
T
k\sum_{T|k}\mu(T)T
k∑T∣kμ(T)T的前缀和
而
∑
x
=
1
⌊
N
k
⌋
x
∑
y
=
1
⌊
M
k
⌋
y
\sum_{x=1}^{⌊\frac N{k}⌋}x\sum_{y=1}^{⌊\frac M{k}⌋}y
∑x=1⌊kN⌋x∑y=1⌊kM⌋y可以
Θ
(
1
)
\Theta(1)
Θ(1)出
利用整除分块优化,时间复杂度为
Θ
(
N
+
T
N
)
\Theta(N+T\sqrt N)
Θ(N+TN)
AC code([bzoj 2693] jzptab)
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int MAXN = 10000005, mod = 1e8+9;
int N, M;
namespace Mobius
{
int mu[MAXN], Prime[MAXN], cnt;
bool IsnotPrime[MAXN];
int sum[MAXN];
void init()
{
sum[1] = 1;
for(int i = 2; i <= MAXN-5; i++)
{
if(!IsnotPrime[i]) Prime[++cnt] = i, sum[i] = 1-i;
for(int j = 1; j <= cnt && i * Prime[j] <= MAXN-5; j++)
{
IsnotPrime[i * Prime[j]] = 1;
if(i % Prime[j] == 0) { sum[i * Prime[j]] = sum[i]; break; }
sum[i * Prime[j]] = 1ll * sum[i] * (1 - Prime[j]) % mod;
}
}
for(int i = 1; i <= MAXN-5; i++)//前缀和
sum[i] = (sum[i-1] + 1ll*sum[i]*i%mod) % mod;
}
int Sum(int N, int M)
{
return ((1ll*N*(N+1)/2) % mod) * ((1ll*M*(M+1)/2) % mod) % mod;
}
int calc(int N, int M)
{
int ret = 0;
for(int i = 1, j; i <= N; i=j+1)//整除分块
{
j = min(N/(N/i), M/(M/i));
ret = (ret + 1ll * (sum[j] - sum[i-1]) % mod * Sum(N/i, M/i) % mod) % mod;
}
return ret;
}
}
using namespace Mobius;
int main ()
{
int T; init();
scanf("%d", &T);
while(T--)
{
scanf("%d%d", &N, &M); if(N > M) swap(N, M);
printf("%d\n", (calc(N, M) + mod) % mod);
}
}
AC code([bzoj 2154] Crash的数字表格)
这道题有个恶心的地方,不能用 M a x n Maxn Maxn来预处理,否则会 T L E TLE TLE,要读入 N N N, M M M后再 O ( N ) O(N) O(N)处理
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int MAXN = 10000005, mod = 20101009;
int N, M;
namespace Mobius
{
int mu[MAXN], Prime[MAXN], cnt;
bool IsnotPrime[MAXN];
int sum[MAXN];
void init()
{
sum[1] = 1;
for(int i = 2; i <= N; i++)
{
if(!IsnotPrime[i]) Prime[++cnt] = i, sum[i] = 1-i;
for(int j = 1; j <= cnt && i * Prime[j] <= N; j++)
{
IsnotPrime[i * Prime[j]] = 1;
if(i % Prime[j] == 0) { sum[i * Prime[j]] = sum[i]; break; }
sum[i * Prime[j]] = 1ll * sum[i] * (1 - Prime[j]) % mod;
}
}
for(int i = 1; i <= N; i++)
sum[i] = (sum[i-1] + 1ll*sum[i]*i%mod) % mod;
}
int Sum(int N, int M)
{
return ((1ll*N*(N+1)/2) % mod) * ((1ll*M*(M+1)/2) % mod) % mod;
}
int calc(int N, int M)
{
int ret = 0;
for(int i = 1, j; i <= N; i=j+1)
{
j = min(N/(N/i), M/(M/i));
ret = (ret + 1ll * (sum[j] - sum[i-1]) % mod * Sum(N/i, M/i) % mod) % mod;
}
return ret;
}
}
using namespace Mobius;
int main ()
{
scanf("%d%d", &N, &M); if(N > M) swap(N, M); init();
printf("%d\n", (calc(N, M) + mod) % mod);
}