zoukankan      html  css  js  c++  java
  • [bzoj2301] [HAOI2011]Problem b

    Description

    对于给出的n个询问,每次求有多少个数对(x,y),满足a≤x≤b,c≤y≤d,且gcd(x,y) = k,gcd(x,y)函数为x和y的最大公约数。

    Input

    第一行一个整数n,接下来n行每行五个整数,分别表示a、b、c、d、k

    Output

    共n行,每行一个整数表示满足要求的数对(x,y)的个数

    Sample Input

    2
    2 5 1 5 1
    1 5 1 5 2
    

    Sample Output

    14
    3
    

    HINT

    100%的数据满足:1≤n≤50000,1≤a≤b≤50000,1≤c≤d≤50000,1≤k≤50000

    Source

    题解

    前置知识:莫比乌斯反演

    题目要求的是这个:

    [ans = sum _ {i=a}^b sum _ {j=c}^d [gcd(i,j)=k] ]

    我们可以利用二位前缀和的思想转化一下,然后求这个:

    [ans = sum _ {i=1}^n sum _ {j=1}^m [gcd(i,j)=k] ]

    (k)除掉:

    [ans= sum _ {i=1}^{lfloor frac{n}{k} floor} sum _ {j=1}^{lfloor frac{m}{k} floor} [gcd(i,j)=1] ]

    然后对于后面的(gcd)莫比乌斯反演下,即:

    [sum _{d|n} mu(d) =[ n=1 ] ]

    带进去得:

    [ans= sum _ {i=1}^{lfloor frac{n}{k} floor} sum _ {j=1}^{lfloor frac{m}{k} floor} sum _{d|i&d|j} mu(d) ]

    然后交换下枚举顺序,先枚举(d),得:

    [egin {align} ans&= sum _dmu(d) sum _{i=1}^{lfloor frac{n}{kd} floor} sum _{j=1}^{lfloor frac{m}{kd} floor} 1 \ &= sum _dmu(d) lfloor frac{n}{kd} floor lfloor frac{m}{kd} floor \ end {align} ]

    然后线筛下(mu),整除分块下,就做完了。

    这里最好是把(n)(m)分别除以(k)后在整除分块,否则亲测会慢一倍,虽然(bzoj)心情好的话卡时限能过。。

    #include<bits/stdc++.h>
    using namespace std;
    
    #define int long long 
    
    void read(int &x) {
    	x=0;int f=1;char ch=getchar();
    	for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-f;
    	for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';x*=f;
    }
    
    void print(int x) {
    	if(x<0) putchar('-'),x=-x;
    	if(!x) return ;print(x/10),putchar(x%10+48);
    }
    void write(int x) {if(!x) putchar('0');else print(x);putchar('
    ');}
    
    const int maxn = 5e4+10;
    
    int mu[maxn],pri[maxn],vis[maxn],tot,T;
    
    void sieve() {
    	mu[1]=1;
    	for(int i=2;i<maxn;i++) {
    		if(!vis[i]) pri[++tot]=i,mu[i]=-1;
    		for(int j=1;j<=tot&&i*pri[j]<maxn;j++) {
    			vis[i*pri[j]]=1;
    			if(!(i%pri[j])) {mu[i*pri[j]]=0;break;}
    			else mu[i*pri[j]]=-mu[i];
    		}
    	}
    	for(int i=1;i<maxn;i++) mu[i]=mu[i]+mu[i-1];
    }
    
    int calc(int n,int m,int k) {
    	int d=1,ans=0;n/=k,m/=k;
    	while(d<=n&&d<=m) {
    		int pre=d;d=min(n/(n/d),m/(m/d));
    		ans+=(n/d)*(m/d)*(mu[d]-mu[pre-1]);
    		d++;
    	}return ans;
    }
    
    signed main() {
    	sieve();read(T);
    	for(int i=1,a,b,c,d,k;i<=T;i++) {
    		read(a),read(b),read(c),read(d),read(k);
    		write(calc(b,d,k)-calc(b,c-1,k)-calc(a-1,d,k)+calc(a-1,c-1,k));
    	}
    	return 0;
    }
    
    
  • 相关阅读:
    你所不了解的静态路由特点及配置
    程序员进阶中--说说这一年的“酸甜苦辣”
    前序、中序、后序遍历的多种非递归实现
    spring依赖注入单元测试:expected single matching bean but found 2
    汉语-汉字:効、效
    汉语-词语:悃愊
    汉语-词语:宽容
    System.Threading.Tasks.TaskFactory.cs
    汉语-词语:高明
    唐-诗:《山居秋暝》
  • 原文地址:https://www.cnblogs.com/hbyer/p/10052719.html
Copyright © 2011-2022 走看看