• 题解 P2257 【YY的GCD】


    神犇 YY 虐完数论后给傻× kAc 出了一题

    给定 N,MN, M1xN1 leq x leq N1yM1 leq y leq Mgcd(x,y)gcd(x, y) 为质数的 (x,y)(x, y) 有多少对。

    pprimi=1nj=1m[gcd(i,j)=p]=pprimi=1npj=1mp[gcd(i,j)=1]=pprimi=1npj=1mpε(gcd(i,j)=1)=pprimi=1npj=1mpε(gcd(i,j))=pprimi=1npj=1mpdgcd(i,j)μ(d)=pprimpdμ(d)i=1np[di]j=1mp[dj]=pprimpdμ(d)nkdmkd egin{aligned} &sum_{pin prim}sum_{i=1}^{n}sum_{j=1}^{m}[gcd(i,j)=p] \ =& sum_{pin prim}sum_{i=1}^{lfloorfrac{n}{p} floor}sum_{j=1}^{lfloorfrac{m}{p} floor}[gcd(i,j)=1]\ =& sum_{pin prim}sum_{i=1}^{lfloorfrac{n}{p} floor}sum_{j=1}^{lfloorfrac{m}{p} floor}varepsilon(gcd(i,j)=1)\ =& sum_{pin prim}sum_{i=1}^{lfloorfrac{n}{p} floor}sum_{j=1}^{lfloorfrac{m}{p} floor}varepsilon(gcd(i,j))\ =& sum_{pin prim}sum_{i=1}^{lfloorfrac{n}{p} floor}sum_{j=1}^{lfloorfrac{m}{p} floor} sum_{dmid gcd(i,j)} mu(d)\ =&sum_{pin prim}sum_{pmid d} mu(d)sum_{i=1}^{lfloorfrac{n}{p} floor}[dmid i]sum_{j=1}^{lfloorfrac{m}{p} floor}[dmid j]\ =&sum_{pin prim}sum_{pmid d} mu(d) lfloor frac{n}{kd} floor frac{m}{kd} floor\ end{aligned}
    设:

    f(p)=pdμ(d)f(p)=sumlimits_{pmid d} mu(d)

    则原式化为:

    =pprimf(p)×nkdmkd egin{aligned} =&sum_{pin prim} f(p) imes lfloor frac{n}{kd} floor frac{m}{kd} floor\end{aligned}

    我们先去预处理 ff 函数

    for(int i=1;i<=cnt;i++)
    	for(int j=1;j*prim[i]<N;j++)
    		f[j*prim[i]]+=mu[j];
    

    就是这里的 ff 数组。

    之后我们就可以求解了。

    我们可以使用数论分块来写这题。

    代码:

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    template<typename T>inline void read(T &FF){
    	T RR=1;FF=0;char CH=getchar();
    	for(;!isdigit(CH);CH=getchar())if(CH=='-')RR=-1;
    	for(;isdigit(CH);CH=getchar())FF=(FF<<1)+(FF<<3)+(CH^48);
    	FF*=RR;
    }
    const int N=1e7+10;
    int prim[N],mu[N],sum[N],cnt,k,T,f[N];
    bool vis[N];
    void init(){
    	mu[1]=1;
    	for(register int i=2;i<N;i++){
    		if(!vis[i]){
    			mu[i]=-1;
    			prim[++cnt]=i;
    		}
    		for(register int j=1;j<=cnt&&i*prim[j]<N;j++){
    			vis[i*prim[j]]=1;
    			if(i%prim[j]==0)break;
    			mu[i*prim[j]]=-mu[i];
    		}
    	}
    	for(int i=1;i<=cnt;i++)
    		for(int j=1;j*prim[i]<N;j++)
    			f[j*prim[i]]+=mu[j];
    	for(register int i=1;i<N;i++)sum[i]=sum[i-1]+f[i];
    }//莫比乌斯反演的板子
    ll calc(int a,int b){
    	ll ans=0;
    	for(register int l=1,r;l<=min(a,b);l=r+1){
    		r=min(a/(a/l),b/(b/l));
    		ans+=(1ll*a/l)*(1ll*b/l)*(sum[r]-sum[l-1]);
    	}
    	return ans;
    }
    int main(){
    	init();
    	for(read(T);T--;){
    		int x,y;
    		read(x);read(y);
    		printf("%lld
    ",calc(x,y));
    	}
    	return 0;
    }
    
  • 相关阅读:
    Java正则表达式入门1
    JAVA中正则表达式总结
    Java正则表达式入门
    java String.valueOf()的作用
    【HDOJ】3601 Coach Yehr’s punishment
    【HDOJ】4601 Letter Tree
    【HDOJ】3686 Traffic Real Time Query System
    【HDOJ】5296 Annoying problem
    【HDOJ】3553 Just a String
    【HDOJ】4426 Palindromic Substring
  • 原文地址:https://www.cnblogs.com/zhaohaikun/p/12816925.html
Copyright © 2020-2023  润新知