• 洛谷 P5176 公约数 题解


    CSDN同步

    原题链接

    我天哪 大大的庆祝一下:

    数论黑题 (T1) 达成!

    激动地不行

    记住套路:乱推 (gcd),欧拉筛模板,然后乱换元,乱换式子,完了整除分块,欧拉筛和前缀和就解决了!

    [sum_{i=1}^nsum_{j=1}^msum_{k=1}^pgcd(icdot j,icdot k,jcdot k) imes gcd(i,j,k) imes left(frac{gcd(i,j)}{gcd(i,k) imes gcd(j,k)}+frac{gcd(i,k)}{gcd(i,j) imes gcd(j,k)}+frac{gcd(j,k)}{gcd(i,j) imes gcd(i,k)} ight) ]

    [= sum_{i=1}^n sum_{j=1}^m sum_{k=1}^p frac{gcd(i,j) imes gcd(i,k) imes gcd(j,k)}{gcd(i,j,k)} imes gcd(i,j,k) imes left(frac{gcd(i,j)}{gcd(i,k) imes gcd(j,k)}+frac{gcd(i,k)}{gcd(i,j) imes gcd(j,k)}+frac{gcd(j,k)}{gcd(i,j) imes gcd(i,k)} ight) ]

    [= sum_{i=1}^n sum_{j=1}^m sum_{k=1}^p gcd(i,j)^2 + gcd(i,k)^2 + gcd(j,k)^2 ]

    [= p imes sum_{i=1}^n sum_{j=1}^m gcd(i,j)^2 + m imes sum_{i=1}^n sum_{k=1}^p gcd(i,k)^2 + n imes sum_{j=1}^m sum_{k=1}^p gcd(j,k)^2 ]

    下面我们只需考虑 (sum_{i=1}^n sum_{j=1}^m gcd(i,j)^2)的值即可。

    [sum_{i=1}^n sum_{j=1}^m gcd(i,j)^2 ]

    [= sum_{d=1}^{min(n,m)} d^2 sum_{i=1}^n sum_{j=1}^m [gcd(i,j) == d] ]

    [= sum_{d=1}^{min(n,m)} d^2 sum_{i=1}^{lfloor frac{n}{d} floor} sum_{j=1}^{lfloor frac{m}{d} floor} [gcd(i,j) == 1] ]

    这里我们要知道 (sum_{i=1}^a sum_{j=1}^b [gcd(i,j) == 1]).

    然后开始莫比乌斯反演。

    令:

    [f_x = sum_{i=1}^a sum_{j=1}^b [gcd(i,j) == x] ]

    [F_x = sum_{i=1}^a sum_{j=1}^b [x | gcd(i,j)] ]

    显然有:

    [F_x = sum_{x|d} f_d ]

    [f_1 = sum_{d=1} F_d imes mu_d ]

    [= sum_{d=1}^{min(n,m)} mu_d imes lfloor frac{n}{d} floor imes lfloor frac{m}{d} floor ]

    回到原式:

    [= sum_{d=1}^{min(n,m)} d^2 sum_{i=1}^{lfloor frac{n}{d} floor} sum_{j=1}^{lfloor frac{m}{d} floor} [gcd(i,j) == 1] ]

    [= sum_{d=1}^{min(n,m)} d^2 sum_{g=1}^{min(lfloor frac{n}{d} floor,lfloor frac{m}{d} floor)} mu_d lfloor frac{n}{g imes d} floor lfloor frac{m}{g imes d} floor ]

    (T = g imes d) ,换 (d|T) 枚举。

    [= sum_{T=1}^{min(n,m)} lfloor frac{n}{T} floor imes lfloor frac{m}{T} floor imes sum_{d|T} d^2 mu{lfloor frac{T}{d} floor} ]

    对于前面的,我们整除分块。

    后面的,是个卷积,两个还都是积性函数,用欧拉筛一下。

    (欧拉筛能解决所有的积性函数。如果不能,就再筛一遍。)

    提醒一句:我们是要对 (n) , (m)(p) 求三次,不要只求一次啊。

    突然感觉黑题也不怎难,会了套路就好

    #pragma GCC optimize(2)
    #include<bits/stdc++.h>
    using namespace std;
    
    typedef long long ll;
    const ll MOD=1e9+7;
    const int N=2e7+1;
    
    inline ll read(){char ch=getchar();int f=1;while(ch<'0' || ch>'9') {if(ch=='-') f=-f; ch=getchar();}
    	ll x=0;while(ch>='0' && ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();return x*f;}
    
    ll T,n,m,p,cnt=0; bool h[N];
    ll prime[N],sum[N],f[N];
    
    inline ll solve(ll n,ll m) {
    	ll ans=0;
    	for(ll i=1,t;i<=min(n,m);i=t+1) {
    		t=min(n/(n/i),m/(m/i));
    		ans=(ans+(n/i)*(m/i)%MOD*((sum[t]-sum[i-1]+MOD)%MOD)%MOD)%MOD;
    	} return ans;
    } //整除分块
    
    inline void Euler() {
    	f[1]=1;
    	for(ll i=2;i<N;i++) {
    		if(!f[i]) prime[++cnt]=i,f[i]=(i*i%MOD-1+MOD)%MOD;
    		for(ll j=1;j<=cnt && i*prime[j]<N;j++) {
    			f[i*prime[j]]=1;
    			if(i%prime[j]==0) {
    				f[i*prime[j]]=f[i]*prime[j]%MOD*prime[j]%MOD;
    				break;
    			} else f[i*prime[j]]=f[i]*f[prime[j]]%MOD;
    		}
    	}
    	for(ll i=1;i<N;i++) sum[i]=(sum[i-1]+f[i])%MOD;
    } //欧拉筛,做前缀和
    
    int main(){
    	Euler(); T=read(); while(T--) {
    		n=read(),m=read(),p=read();
    		printf("%lld
    ",(p*solve(n,m)%MOD+m*solve(n,p)%MOD+n*solve(m,p)%MOD)%MOD);
    	} //别忘了3次轮换
    	return 0;
    }
    
    
  • 相关阅读:
    java分页查询--oracle
    Tomcat Excel中的数据导出到页面中显示
    接口调用类3
    接口工具类2
    接口工具类
    redis 对外访问
    Spring 项目启动时执行
    scp 本地上传/下载服务器文件
    CentOS 安装 rabbitMQ
    卸载rabbitMQ
  • 原文地址:https://www.cnblogs.com/bifanwen/p/12531298.html
Copyright © 2020-2023  润新知