zoukankan      html  css  js  c++  java
  • P5176 公约数

    P5176 公约数

    说在前面的话:

    这题后面的线性筛和 P4449 于神之怒加强版 很像,建议这两道题连着做,巩固一下非常规函数线性筛顺便水个双倍经验。但是网上于神之怒的题解都过于简略(我比较菜),看不懂,做于神之怒的时候很痛苦,因此本文线性筛的过程尽量详细写,让初学者看懂,看不懂欢迎在评论区提问,NOIP前应该能做到1天内回复。

    [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) ]

    那个 (gcd(ij,jk,ki)) 一看就是要化掉的。

    显然应该从质因子的幂次入手,设 (i=p^a,j=p^b,k=p^c)

    那么 (p)(gcd(ij,jk,,ki)) 的贡献就是 (p^{min(a+b,b+c,c+a)})

    考虑构造一个东西来表示 (min(a+b,b+c,c+a)) 。不妨 (ale ble c) (显然排序不会影响结果)

    (min(a+b,b+c,c+a)=a+b=min(a,b)+min(b,c)+min(a,c)-min(a,b,c))

    转成 (gcd) 的写法就是 (gcd(ij,jk,ki)=dfrac{gcd(i,j)gcd(j,k)gcd(k,i)}{gcd(i,j,k)})

    带回原式发现良心出题人非常非常非常良心地帮你约掉了 (gcd(i,j,k)) 这种三元 (gcd) 以及所有分母

    化简一下,原式(=sumlimits_{i=1}^{A}sumlimits_{j=1}^{B}sumlimits_{k=1}^{C}gcd(i,j)^2+gcd(j,k)^2+gcd(k,i)^2)

    发现凉心出题人非常非常非常凉心把 (gcd) 平方了。

    原式显然可以分成三部分算。

    先算

    [sum_{i=1}^{A}sum_{j=1}^{B}sum_{i=1}^{C}gcd(i,j)^2\ =Csum_{i=1}^{A}sum_{j=1}^{B}gcd(i,j)^2\ =Csum_{d=1}^{A} sum_{i=1}^{A}sum_{j=1}^{B}[gcd(i,j)==d]d^2\ =Csum_{d=1}^{A}d^2sum_{i=1}^{frac{A}{d}}sum_{j=1}^{frac{B}{d}}[gcd(i,j)==1]\ =Csum_{d=1}^{A}d^2sum_{i=1}^{frac{A}{d}}sum_{j=1}^{frac{B}{d}}sum_{x|gcd(i,j)}mu(x)\ =Csum_{d=1}^{A}d^2sum_{x=1}^{frac{A}{d}}mu(x)dfrac{A}{dx}dfrac{B}{dx}\ =Csum_{d=1}^{A}d^2sum_{T=1,d|T}^{A}mu(dfrac{T}{d})dfrac{A}{T}dfrac{B}{T}\ =sum_{T=1}^{A}dfrac{A}{T}dfrac{B}{T}sum_{d|T}d^2mu(dfrac{T}{d}) ]

    现在的问题在于 (f(T)=sum_{d|T}d^2mu(dfrac{T}{d})) ,这个东西一出来就可以 (O(sqrt{n})) 整除分块了。

    仔细观察发现这是个积性函数,可以线性筛, (2e7) 怕他啥((color{black}{ exttt{c}}color{red}{ exttt{yn2006}}) (O(nln n)) 暴力筛都过去了)。

    (pin prime) ,则

    [f(p)=mu(1) imes p^2+mu(p) imes 1^2=p^2-1\ ]

    接下去处理掉 (p|i) 的情况就可以线性筛了。

    (x)(p)(T) 中的最高幂次

    发掘 (mu) 的性质,当且仅当 (d=p^x)(d=p^{x-1}) 时有贡献((mu(dfrac{T}{d})!=0))。

    带入得

    (f(p^x)=p^{2x}-p^{2(x-1)})

    (f(p^{x+1})=p^{2(x+1)}-p^{2x}=p^2(p^{2x}-p^{2(x-1)})=p^2f(p^x))

    ( herefore f(ip)=f(i) imes p^2(p|i)) ,综合如下:

    [f(T)= egin{cases} T^2-1(Tin mathcal{prime})\ f(i)*p^2(p|i)\ f(i)*f(p)(otherwise) end{cases} ]

    可以线性筛了

    提供一组大样例以供调试

    Input
    1
    10000000 5000000 20000000
    Output
    913785109
    
    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    #define pb(x) push_back(x)
    #define mkp(x,y) make_pair(x,y)
    //#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
    //char buf[1<<21],*p1=buf,*p2=buf;
    inline int read() {
    	int x=0,f=1;char ch=getchar();
    	while(!isdigit(ch)) {if(ch=='-')f=-1;ch=getchar();}
    	while(isdigit(ch))x=x*10+(ch^48),ch=getchar();
    	return x*f;
    }
    const int N=20000005;
    const int mod=1000000007;
    int A,B,C;
    int pri[N/10],cnt,s[N];
    bool vis[N];
    void Sieve(const int N=20000000){
    	s[1]=1;
    	for(int i=2;i<=N;++i){
    		if(!vis[i])pri[++cnt]=i,s[i]=1ll*i*i%mod-1;
    		for(int j=1;j<=cnt&&i*pri[j]<=N;++j){
    			vis[i*pri[j]]=1;
    			if(i%pri[j]==0){s[i*pri[j]]=1ll*s[i]*pri[j]%mod*pri[j]%mod;break;}
    			s[i*pri[j]]=1ll*s[i]*s[pri[j]]%mod;
    		}
    	}
    	for(int i=1;i<=N;++i)s[i]=(s[i]+s[i-1])%mod;
    }
    int f(int A,int B,int C){
    	int res=0;
    	for(int l=1,r,mx=min(A,B);l<=mx;l=r+1){
    		r=min(A/(A/l),B/(B/l));
    		res=(res+1ll*(A/l)*(B/l)%mod*(s[r]-s[l-1])%mod)%mod;
    	}
    	return 1ll*res*C%mod;
    }
    signed main(){
    	Sieve();
    	for(int T=read();T;--T){
    		A=read(),B=read(),C=read();
    		printf("%d
    ",(((f(A,B,C)+f(B,C,A))%mod+f(C,A,B))%mod+mod)%mod);
    	}
    }
    
    路漫漫其修远兮,吾将上下而求索
  • 相关阅读:
    Memcache第一篇---基础教程
    【分享】一位技术人员成长历程
    simhash
    Cookie mapping技术
    压缩编码基础知识
    shell vim--处理二进制文本
    CSDN泄漏数据完整分析
    day17 isinstance type issubclass 反射
    day16 类之间的关系 特殊成员
    day14 面向对象
  • 原文地址:https://www.cnblogs.com/zzctommy/p/13764162.html
Copyright © 2011-2022 走看看