GCD与莫比乌斯反演的勾当

目录

  • 机房最后一个学懵逼钨丝的人
    • 题目一
    • 题目
    • bzoj1101

机房最后一个学懵逼钨丝的人

题目一

链接

题目没找到
\(\sum_{1}^{n}\sum_{1}^{m}gcd(i,j)\)

式子

\(\sum\limits_{i=1}^{N}\sum\limits_{j=1}^{M} gcd(i,j)\)
\(\sum\limits_{k=1}^{min(N,M)} k*\sum\limits_{i=1}^{N}\sum\limits_{j=1}^{M} [gcd(i,j)==k]=\sum\limits_{k=1}^{min(N,M)} k*\sum\limits_{i=1}^{\frac{N}{k}}\sum\limits_{j=1}^{\frac{M}{k}} [gcd(i,j)==1]\)
\(看这部分\sum\limits_{i=1}^{N}\sum\limits_{j=1}^{M} [gcd(i,j)==k]\)
\(g(d)=\sum\limits_{i=1}^{N}\sum\limits_{j=1}^{M} [gcd(i,j)==d]\)
\(f(n)=\sum\limits_{n|d}g(d)=[\frac{N}{d}][\frac{M}{d}]\)(显然,不说了)
\(g(n)=\sum\limits_{n|d}\mu(\frac{d}{n})f(d)\)
\(g(1)=\sum\limits_{i=1}^{min(N,M)}\mu(i)[\frac{N}{i}][\frac{M}{i}]\)
\(ans=\sum\limits_{k=1}^{min(N,M)} k*\sum\limits_{i=1}^{min(N/k,M/k)}\mu(i)[\frac{N/k}{i}][\frac{M/k}{i}]\)
除法分块嵌套复杂度\(O(n)\)

注意

除数不为0

代码

/*
segima gcd n,m
*/
#include 
#include 
#include 
#define ll long long
using namespace std;
const int N=15000007,mod=1e9+7;
int read() {int x=0,f=1;char s=getchar();for(;s>'9'||s<'0';s=getchar()) if(s=='-') f=-1;for(;s>='0'&&s<='9';s=getchar()) x=x*10+s-'0';return x*f;
}
int pri[N/10],mu[N],cnt;
bool vis[N];
void Euler(int n) {vis[1]=mu[1]=1;for(int i=2;i<=n;++i) {if(!vis[i]) pri[++cnt]=i,mu[i]=-1;for(int j=1;j<=cnt&&i*pri[j]<=n;++j) {vis[ i*pri[j] ] = 1;if(i % pri[j] == 0) {mu[ i*pri[j] ] = 0;break;} elsemu[ i*pri[j] ] = -mu[i];}}for(int i=1;i<=n;++i) mu[i]+=mu[i-1];
}
int g(int N,int M,int n) {int ans=0;for(int l=1,r=1;l<=n;l=r+1) {r=min(N/(N/l),M/(M/l));ans=(ans+1LL*(mu[r]-mu[l-1]+mod)%mod*(N/l)%mod*(M/l)%mod)%mod;}return ans;
}
ll calc(int a) {return 1LL*a*(a+1)%mod*500000004%mod;}
int main() {int N=read(),M=read(),n=min(N,M),ans=0;Euler(n);for(int l=1,r=1;l<=n;l=r+1) {r=min(N/(N/l),M/(M/l));ans=(1LL*ans+(1LL*(calc(r)-calc(l-1))%mod+mod)%mod*1LL*g(N/l,M/l,min(N/l,M/l)))%mod;}cout<

题目

类似的 差不多=多组询问的T1
https://www.luogu.org/problemnew/show/P2257

链接&&问题

\(\sum\limits_{i=1}^{n}\sum\limits_{j=1}^{m}[gcd(i,j)==pri]\)

公式

\(\sum\limits_{k=1}^{N}\sum\limits_{i=1}^{n}\sum\limits_{j=1}^{m}[gcd(i,j)==k]\)
扣出\(\sum\limits_{i=1}^{n}\sum\limits_{j=1}^{m}[gcd(i,j)==k]\)
啊哈,熟悉的套路
$ 此处省略,在T1或T2都有$
\(ans=\sum\limits_{p=pri}^{min(N,M)} \sum\limits_{i=1}^{N/p}\mu(i)[\frac{N/p}{i}][\frac{M/p}{i}]\)
A了?1000组询问T飞了
\(\sum\limits_{p=pri} \sum\limits_{i=1}^{N/p}\mu(i)[\frac{N/p}{i}][\frac{M/p}{i}]\)
\(\sum\limits_{p=pri} \sum\limits_{i=1}^{N/p}\mu(\frac{k}{p})[\frac{N}{k}][\frac{M}{k}]\)
\(\sum\limits_{k=1}^{N}\sum\limits_{p=pri,p|k} \mu(\frac{k}{p})[\frac{N}{k}][\frac{M}{k}]\)
\(z(k)=\sum\limits_{p=pri,p|k} \mu(\frac{k}{p})\)
线性筛预处理出z的前缀和就可以了
它的证明不错
https://orzsiyuan.com/articles/problem-Luogu-2257-YY-GCD/

代码

#include 
#include 
#include 
#define ll long long
using namespace std;
const int N=10000007,mod=1e9+7;
int read() {int x=0,f=1;char s=getchar();for(;s>'9'||s<'0';s=getchar()) if(s=='-') f=-1;for(;s>='0'&&s<='9';s=getchar()) x=x*10+s-'0';return x*f;
}
int pri[N/10],mu[N],cnt,z[N];
bool vis[N];
void Euler(int n) {vis[1]=mu[1]=1;for(int i=2;i<=n;++i) {if(!vis[i]) pri[++cnt]=i,mu[i]=-1,z[i]=mu[1];for(int j=1;j<=cnt&&i*pri[j]<=n;++j) {vis[ i*pri[j] ] = 1;if(i % pri[j] == 0) {mu[ i*pri[j] ] = 0;z[ i*pri[j] ] = mu[i];break;} else {mu[ i*pri[j] ] = -mu[i];z[ i*pri[j] ] = -z[i] + mu[i];}}}for(int i=1;i<=n;++i) z[i]+=z[i-1];
}
int g(int N,int M,int n) {ll ans=0;for(int l=1,r=1;l<=n;l=r+1) {r=min(N/(N/l),M/(M/l));ans=ans+1LL*(z[r]-z[l-1])*(N/l)*(M/l);}return ans;
}
int main() {Euler(10000000);int T=read();while(T--) {int a=read(),b=read();printf("%lld\n",g(a,b,min(a,b)));}return 0;
}

bzoj1101

链接

https://www.lydsy.com/JudgeOnline/problem.php?id=1101

式子

同楼上,或许,比他还要简单的多

代码

#include 
#include 
#include 
#define ll long long
using namespace std;
const int N=100007,mod=1e9+7;
int read() {int x=0,f=1;char s=getchar();for(;s>'9'||s<'0';s=getchar()) if(s=='-') f=-1;for(;s>='0'&&s<='9';s=getchar()) x=x*10+s-'0';return x*f;
}
int pri[N/10],mu[N],cnt;
bool vis[N];
void Euler(int n) {vis[1]=mu[1]=1;for(int i=2;i<=n;++i) {if(!vis[i]) pri[++cnt]=i,mu[i]=-1;for(int j=1;j<=cnt&&i*pri[j]<=n;++j) {vis[ i*pri[j] ] = 1;if(i % pri[j] == 0) {mu[ i*pri[j] ] = 0;break;} elsemu[ i*pri[j] ] = -mu[i];}}for(int i=1;i<=n;++i) mu[i]+=mu[i-1];
}
int g(int N,int M,int n) {ll ans=0;for(int l=1,r=1;l<=n;l=r+1) {r=min(N/(N/l),M/(M/l));ans=ans+1LL*(mu[r]-mu[l-1])*(N/l)*(M/l);}return ans;
}
int main() {// freopen("11.in","r",stdin);// freopen("a.out","w",stdout);Euler(100000);int T=read();while(T--) {int a=read(),b=read(),c=read();printf("%lld\n",g(a/c,b/c,min(a/c,b/c)));}return 0;
}

转载于:https://www.cnblogs.com/dsrdsr/p/10373532.html


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部