BZOJ 2154 Crash的数字表格
跟着litble学套路
Solution
题目要求:
开始疯狂套路
0x00
首先化为常见的
gcd
g
c
d
的形式
0x01
然后枚举
gcd
g
c
d
0x02
接着将
gcd(a,b)==d
g
c
d
(
a
,
b
)
==
d
变为
gcd(a/d,b/d)==1
g
c
d
(
a
/
d
,
b
/
d
)
==
1
0x03
其次我们通过莫比乌斯函数的性质
将 [gcd(i,j)==1] [ g c d ( i , j ) == 1 ] 转化为 ∑t|gcd(i,j)μ(t) ∑ t | g c d ( i , j ) μ ( t ) ,即 ∑t|i∧t|jμ(t) ∑ t | i ∧ t | j μ ( t )
0x04
下一步枚举
t
t
同时也会变形,变为枚举
t
t
的倍数
假设 sum(n) s u m ( n ) 表示 1⋯n 1 ⋯ n 的和,即 ∑ni=1i ∑ i = 1 n i
则原式为
0x05
设
T=td
T
=
t
d
,枚举
T
T
0x06
0x06
设
F(T)=T∑nt|Tt∗μ(t)
F
(
T
)
=
T
∑
t
|
T
n
t
∗
μ
(
t
)
话说差点忘了
d
d
导致没推出来,想了好久
搞定
你以为这样就完了??
不存在的
还有一个反套路的点
如何求
F(T)
F
(
T
)
?
显然是卷积的形式
那么它同时也是一个积性函数
所以按理来说应该可以线性筛
我们考虑新增一个质因数
p
p
原来处理出来了
若
imodp≠0
i
mod
p
≠
0
若 imodp=0 i mod p = 0
代码如下:
#include <bits/stdc++.h>
using namespace std;
const int N = 10000005;
const int mod = 20101009;
int pri[N],tot,mu[N],n,m;
long long f[N];
long long s[N];
bool mark[N];
void get() {
mu[1]=1;
f[1]=1;
for(register int i=2;i<=10000000;++i) {
if(!mark[i]) {
pri[++tot]=i;
f[i]=1-i;
mu[i]=-1;
}
for(register int j=1;j<=tot && pri[j]*i<=10000000;++j) {
mark[i*pri[j]]=1;
if(i%pri[j]==0) {
f[i*pri[j]]=f[i];
break;
}
f[i*pri[j]]=f[i]*f[pri[j]]%mod;
mu[i*pri[j]]=-mu[i];
}
}
for(register int i=1;i<=10000000;++i) {
f[i]=((f[i]*i)%mod+f[i-1])%mod;
s[i]=(s[i-1]+i)%mod;
}
}
int main() {
get();
scanf("%d%d",&n,&m);
if(n>m) swap(n,m);
int pos=0,ans=0;
for(int i=1;i<=n;i=pos+1) {
pos=min(n/(n/i),m/(m/i));
ans=(ans+(f[pos]-f[i-1]+mod)%mod*s[n/i]%mod*s[m/i]%mod)%mod;
}
printf("%d\n",(ans+mod)%mod);
return 0;
}