zoukankan      html  css  js  c++  java
  • 题解 P2522 【[HAOI2011]Problem b】

    对于给出的 nn 个询问,每次求有多少个数对 (x,y)(x,y),满足 axba le x le bcydc le y le d,且 gcd(x,y)=kgcd(x,y) = kgcd(x,y)gcd(x,y) 函数为 xxyy 的最大公约数。

    i=abj=cd[gcd(i,j)=k] sumlimits_{i=a}^{b} sumlimits_{j=c}^{d} [gcd(i,j)=k]

    函数 f(x,y)f(x,y) 为:

    i=1xj=1y[gcd(i,j)=k] sumlimits_{i=1}^{x} sumlimits_{j=1}^{y} [gcd(i,j)=k]

    那么,运用容斥原理,原式就 =f(b,d)f(a,d)f(b,c)+f(a,c)= f(b,d) - f(a,d) - f(b,c) + f(a,c)

    所以现在问题就转换为了求 ff 函数。

    i=1xj=1y[gcd(i,j)=k]=i=1nkj=1mk[gcd(i,j)=1]=i=1nkj=1mkε(gcd(i,j))=i=1nkj=1mkdgcd(i,j)μ(d)=d=1μ(d)i=1nk[di]j=1mk[dj]=d=1μ(d)nkdmkd egin{aligned} &sumlimits_{i=1}^{x} sumlimits_{j=1}^{y} [gcd(i,j)=k] \ =& sum_{i=1}^{lfloorfrac{n}{k} floor}sum_{j=1}^{lfloorfrac{m}{k} floor}[gcd(i,j)=1]\ =& sum_{i=1}^{lfloorfrac{n}{k} floor}sum_{j=1}^{lfloorfrac{m}{k} floor}varepsilon(gcd(i,j))\ =& sum_{i=1}^{lfloorfrac{n}{k} floor}sum_{j=1}^{lfloorfrac{m}{k} floor}sum_{d mid gcd(i,j) }mu(d)\ =& sum_{d=1 }mu(d)sum_{i=1}^{lfloorfrac{n}{k} floor}[d mid i]sum_{j=1}^{lfloorfrac{m}{k} floor}[d mid j]\ =&sum_{d=1}mu(d)lfloorfrac{n}{kd} floorlfloorfrac{m}{kd} floor end{aligned}

    我们可以使用数论分块进行求解

    代码:

    #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=50010;
    int prim[N],mu[N],sum[N],cnt,k,T;
    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(register int i=1;i<N;i++)sum[i]=sum[i-1]+mu[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 a,b,c,d;
    		read(a);read(b);read(c);read(d);read(k);
    		a--;c--;a/=k;b/=k;c/=k;d/=k;
    		printf("%lld
    ",calc(b,d)-calc(b,c)-calc(a,d)+calc(a,c));
    	}
    	return 0;
    }
    
  • 相关阅读:
    UPS FAQ-不错的UPS资料
    HPL.dat FAQ
    Fortran77计算某段代码的CPU运行时间
    存储知识 什么是LUN?LUN有什么用?对理解存储设备很有好处
    HPL.dat Tune
    UPS-瓦特(W)和伏安(VA):易混淆的两个概念
    mysql sql 索引相关用法,加快查询速度
    mysql 数据库分类设计方法与PHP结合
    c# SQLServer 数据库连接类
    .net上传图片生成大小缩略图
  • 原文地址:https://www.cnblogs.com/zhaohaikun/p/12816926.html
Copyright © 2011-2022 走看看