如果不知道莫比乌斯 这里有我的超精简版入门Mobius
记录我初学莫比乌斯做了整整一天还迷迷糊糊
题目简述:
求 ∑ i = 1 n ∑ j = 1 m d ( i j ) d ( i j ) 为 i ∗ j 的 约 数 ∑_{i=1}^n∑_{j=1}^md(ij)\\d(ij)为i*j的约数 i=1∑nj=1∑md(ij)d(ij)为i∗j的约数(多组数据)
必要性质:
d ( i j ) = ∑ x ∣ i ∑ y ∣ j g c d ( x , y ) = 1 d(ij)=∑_{x|i}∑_{y|j}gcd(x,y)=1 d(ij)=x∣i∑y∣j∑gcd(x,y)=1
证明:
不会
解题思路:
所 求 即 ∑ i = 1 n ∑ j = 1 m ∑ x ∣ i ∑ y ∣ j g c d ( x , y ) = 1 所求即∑_{i=1}^n∑_{j=1}^m∑_{x|i}∑_{y|j}gcd(x,y)=1 所求即i=1∑nj=1∑mx∣i∑y∣j∑gcd(x,y)=1 根 据 莫 比 乌 斯 函 数 的 性 质 可 转 换 为 ∑ i = 1 n ∑ j = 1 m ∑ x ∣ i ∑ y ∣ j ∑ d ∣ g c d ( x , y ) μ ( d ) 根据莫比乌斯函数的性质可转换为\\ ∑_{i=1}^n∑_{j=1}^m∑_{x|i}∑_{y|j}∑_{d|gcd(x,y)}μ(d)\\ 根据莫比乌斯函数的性质可转换为i=1∑nj=1∑mx∣i∑y∣j∑d∣gcd(x,y)∑μ(d) 转 换 为 转换为\\ 转换为 ∑ i = 1 n ∑ j = 1 m ∑ x ∣ i ∑ y ∣ j ∑ d = 1 m i n ( n , m ) μ ( d ) ∗ [ d ∣ g c d ( x , y ) ] ∑_{i=1}^n∑_{j=1}^m∑_{x|i}∑_{y|j}∑_{d=1}^{min(n,m)}μ(d)*[d|gcd(x,y)] i=1∑nj=1∑mx∣i∑y∣j∑d=1∑min(n,m)μ(d)∗[d∣gcd(x,y)] 即 ∑ d = 1 m i n ( n , m ) μ ( d ) ∑ i = 1 n ∑ j = 1 m ∑ x ∣ i ∑ y ∣ j [ d ∣ g c d ( x , y ) ] 即\\ ∑_{d=1}^{min(n,m)}μ(d)∑_{i=1}^n∑_{j=1}^m∑_{x|i}∑_{y|j}[d|gcd(x,y)]\\ 即d=1∑min(n,m)μ(d)i=1∑nj=1∑mx∣i∑y∣j∑[d∣gcd(x,y)] 每 个 d 如 果 在 当 前 x , y 处 合 法 , 那 么 在 x , y 的 倍 数 处 也 一 定 合 法 , 即 每个d如果在当前x,y处合法,那么在x,y的倍数处也一定合法,即\\ 每个d如果在当前x,y处合法,那么在x,y的倍数处也一定合法,即 ∑ d = 1 m i n ( n , m ) μ ( d ) ∑ x = 1 n ∑ y = 1 m [ d ∣ g c d ( x , y ) ] ⌊ n x ⌋ ⌊ m y ⌋ ∑_{d=1}^{min(n,m)}μ(d)∑_{x=1}^n∑_{y=1}^m[d|gcd(x,y)]\lfloor\frac{n}{x}\rfloor\lfloor \frac{m}{y}\rfloor\\ d=1∑min(n,m)μ(d)x=1∑ny=1∑m[d∣gcd(x,y)]⌊xn⌋⌊ym⌋ [ d ∣ g c d ( x , y ) ] 的 意 义 即 为 x , y 的 公 因 数 [d|gcd(x,y)]的意义即为x,y的公因数 [d∣gcd(x,y)]的意义即为x,y的公因数 下 面 进 行 枚 举 项 转 换 , 直 接 枚 举 倍 数 \\下面进行枚举项转换,直接枚举倍数\\ 下面进行枚举项转换,直接枚举倍数 ∑ d = 1 m i n ( n , m ) μ ( d ) ∑ x = 1 n / d ∑ y = 1 m / d ⌊ n d x ⌋ ⌊ m d y ⌋ 即 ∑_{d=1}^{min(n,m)}μ(d)∑_{x=1}^{n/d}∑_{y=1}^{m/d}\lfloor\frac{n}{dx}\rfloor\lfloor \frac{m}{dy}\rfloor \\即 d=1∑min(n,m)μ(d)x=1∑n/dy=1∑m/d⌊dxn⌋⌊dym⌋即 ∑ d = 1 m i n ( n , m ) μ ( d ) ( ∑ x = 1 n / d ⌊ n d x ⌋ ) ( ∑ y = 1 m / d ⌊ m d y ⌋ ) ∑_{d=1}^{min(n,m)}μ(d)(∑_{x=1}^{n/d}\lfloor\frac{n}{dx}\rfloor)(∑_{y=1}^{m/d}\lfloor \frac{m}{dy}\rfloor)\\ d=1∑min(n,m)μ(d)(x=1∑n/d⌊dxn⌋)(y=1∑m/d⌊dym⌋)
对 于 多 组 数 据 我 们 即 可 预 处 理 ∑ x = 1 n n x 提 高 速 率 对于多组数据我们即可预处理∑_{x=1}^{n}\frac{n}{x}提高速率 对于多组数据我们即可预处理x=1∑nxn提高速率
#include
#include
using namespace std;
#define N 50010
int T;
int mu[N],prim[N],cnt,k,g[N];
long long sum[N];
bool vis[N];
inline void get(int n){
mu[1]=1;
for(int i=2;i<=n;i++){
if(!vis[i]){//i为质数
mu[i]=-1;prim[++cnt]=i;
}
for(int j=1;j<=cnt&&i*prim[j]<=n;j++)
{
vis[i*prim[j]]=1;
if(i%prim[j]==0)break;//i*prim[j]指数的大于1
else mu[i*prim[j]]=-mu[i];
}
}
for(int i=1;i<=n;i++)sum[i]=sum[i-1]+(long long)mu[i];
for(int i=1;i<=n;i++){
long long ans=0;
for(int l=1,r;l<=i;l=r+1){
r=(i/(i/l));
ans+=(r-l+1)*1ll*(i/l);
}
g[i]=ans;
}
}
inline long long calc(int a,int b){
int maxx;
long long ans=0;
maxx=min(a,b);
for(int l=1,r;l<=maxx;l=r+1){
r=min(a/(a/l),b/(b/l));
ans+=1ll*g[a/l]*g[b/l]*(sum[r]-sum[l-1]);
}
return ans;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cin>>T;
get(N);
while(T--){
int a,b;
cin>>a>>b;
cout<<calc(a,b)<<endl;
}
return 0;
}