zoukankan      html  css  js  c++  java
  • bzoj2045: 双亲数&bzoj1101: [POI2007]Zap

    传送门:http://www.lydsy.com:808/JudgeOnline/problem.php?id=1101

    思路:设a<b

    求的就是f(a,b,d)=ΣΣ[gcd(i,j)==d](1<=i<=a,1<=j<=b)

    又有公式Σmiu(d) =[n==1] (d|n) //miu是莫比乌斯函数

    把n用gcd(i,j)代入得

    ΣΣΣmiu(d)(d|gcd(i,j),1<=i<=a,1<=j<=b)

    =Σmiu(d)*(a/d)*(b/d)分段统计即可

    分成a/d和b/d都相同的2*sqrt(n)段,乘上这一段的miu的和即可O(sqrt(n))回答了

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int maxn=50010;
    int mu[maxn],A,B,d,pri[maxn],tot,ans,cas,smu[maxn];bool isp[maxn];
    
    void prework(){
    	memset(isp,1,sizeof(isp));
    	isp[1]=0,mu[1]=1;
    	for (int i=2;i<=maxn-10;i++){
    		if (isp[i]) mu[i]=-1,pri[++tot]=i;
    		for (int j=1;j<=tot&&i*pri[j]<=maxn-10;j++){
    			isp[i*pri[j]]=0;
    			if (!(i%pri[j])){mu[i*pri[j]]=0;break;}
    			mu[i*pri[j]]=mu[i]*-1;
    		}
    	}
    	for (int i=1;i<=maxn-10;i++) smu[i]=smu[i-1]+mu[i];
    	//for (ll i=1;i<=50;i++) printf("%lld %d
    ",i,isp[i]);
    }
    
    int getans(int a,int b){
    	int ans=0,ed=0;
    	for (int st=1;st<=B;st=ed+1){
    		ed=min(a/(a/st),b/(b/st));
    		ans+=(smu[ed]-smu[st-1])*(a/st)*(b/st);
    	}
    	return ans;
    }
    
    int main(){
    	prework();
    	scanf("%d",&cas);
    	while (cas--){
    		ans=0;
    		scanf("%d%d%d",&A,&B,&d);
    		if (A<B) swap(A,B);A/=d,B/=d;
    		printf("%d
    ",getans(A,B));
    	}
    	return 0;
    }
    


  • 相关阅读:
    缓存三大问题及解决方案
    布隆过滤器
    maven 详解
    Netty是什么?
    select、poll、epoll简介
    IO
    Java并发编程:Synchronized及其实现原理
    Java并发之AQS详解
    原子更新字段类
    AtomicStampedReference解决ABA问题
  • 原文地址:https://www.cnblogs.com/thythy/p/5493521.html
Copyright © 2011-2022 走看看