zoukankan      html  css  js  c++  java
  • 洛谷 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;
    }
    
    
  • 相关阅读:
    支持向量机SVM知识点概括
    决策树知识点概括
    HDU 3081 Marriage Match II
    HDU 3572 Task Schedule
    HDU 4888 Redraw Beautiful Drawings
    Poj 2728 Desert King
    HDU 3926 Hand in Hand
    HDU 1598 find the most comfortable road
    HDU 4393 Throw nails
    POJ 1486 Sorting Slides
  • 原文地址:https://www.cnblogs.com/bifanwen/p/12531298.html
Copyright © 2011-2022 走看看