zoukankan      html  css  js  c++  java
  • GCD与莫比乌斯反演的勾当

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

    题目一

    链接

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

    式子

    (sumlimits_{i=1}^{N}sumlimits_{j=1}^{M} gcd(i,j))
    (sumlimits_{k=1}^{min(N,M)} k*sumlimits_{i=1}^{N}sumlimits_{j=1}^{M} [gcd(i,j)==k]=sumlimits_{k=1}^{min(N,M)} k*sumlimits_{i=1}^{frac{N}{k}}sumlimits_{j=1}^{frac{M}{k}} [gcd(i,j)==1])
    (看这部分sumlimits_{i=1}^{N}sumlimits_{j=1}^{M} [gcd(i,j)==k])
    (g(d)=sumlimits_{i=1}^{N}sumlimits_{j=1}^{M} [gcd(i,j)==d])
    (f(n)=sumlimits_{n|d}g(d)=[frac{N}{d}][frac{M}{d}])(显然,不说了)
    (g(n)=sumlimits_{n|d}mu(frac{d}{n})f(d))
    (g(1)=sumlimits_{i=1}^{min(N,M)}mu(i)[frac{N}{i}][frac{M}{i}])
    (ans=sumlimits_{k=1}^{min(N,M)} k*sumlimits_{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 <algorithm>
    #include <iostream>
    #include <cstdio>
    #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;
    			} else
    				mu[ 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<<ans<<"
    ";
    	//  ans=0;
    	// for(int i=1;i<=N;++i) {
    	// 	for(int j=1;j<=M;++j) {
    	// 		ans=(ans+__gcd(i,j))%mod;
    	// 	}
    	// }
    	// cout<<ans;
    	return 0;
    }
    
    
    

    题目

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

    链接&&问题

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

    公式

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

    代码

    #include <algorithm>
    #include <iostream>
    #include <cstdio>
    #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
    ",g(a,b,min(a,b)));
    	}
    	return 0;
    }
    
    

    bzoj1101

    链接

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

    式子

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

    代码

    #include <algorithm>
    #include <iostream>
    #include <cstdio>
    #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;
    			} else
    				mu[ 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
    ",g(a/c,b/c,min(a/c,b/c)));
    	}
    	return 0;
    }
    
    
    
  • 相关阅读:
    curl命令学习笔记
    IOS安全测试思维导图
    Hello World
    Hive SQL使用和数据加载的一点总结
    采用最低松弛度优先调度的实时系统调度程序
    MongoDB Map Reduce速度提升20倍的优化宝典
    释放时间不同可中断平行机问题在线算法
    RPC框架系列——Avro
    Solr 3.6.2索引MySQL数据库配置过程
    IKAnalyzer 独立使用 配置扩展词库
  • 原文地址:https://www.cnblogs.com/dsrdsr/p/10373532.html
Copyright © 2011-2022 走看看