• luogu P3455 [POI2007]ZAP-Queries |莫比乌斯反演


    题目描述

    密码学家正在尝试破解一种叫 BSA 的密码。

    他发现,在破解一条消息的同时,他还需要回答这样一种问题:

    给出 (a,b,d),求满足 (1 leq x leq a)(1 leq y leq b),且 (gcd(x,y)=d) 的二元组 ((x,y)) 的数量。

    因为要解决的问题实在太多了,他便过来寻求你的帮助。

    输入格式

    输入第一行一个整数 (n),代表要回答的问题个数。

    接下来 (n) 行,每行三个整数 (a,b,d)

    输出格式

    对于每组询问,输出一个整数代表答案。


    (f(x)=sum_{x=1}^asum_{y=1}^b [gcd(x,y)=d])

    (f(x)=sum_{x=1}^{a/d}sum_{y=1}^{b/d}[gcd(x,y)=1])

    (F(x)=sum_{x|d}^n f(x))=(lfloor{n/x} floor) * (lfloor{m/x} floor)

    (f(x)=sum_{x|d}^n u(d/x)*F(d))

    #include<cmath>
    #include<cstdio>
    #include<iostream>
    using namespace std;
    const int N=5e4+5,M=5e4;
    int mu[N],pri[N],tot,n;
    bool vis[N];
    inline int read(){
        int s = 0; char ch = getchar();
        while(ch < '0' || ch > '9')ch = getchar();
        while(ch >= '0' && ch <= '9') s = s * 10 + ch - '0', ch = getchar();
        return s ;
    }
    signed main(){
    	n=read();
    	mu[1]=vis[0]=vis[1]=1;
    	for(int i=2;i<=M;i++){
    		if(!vis[i]){ mu[i]=-1; pri[++tot]=i; }
    		for(int j=1;j<=tot&&pri[j]*i<=M;j++){
    			vis[pri[j]*i]=1;
    			if(i%pri[j]==0){ mu[pri[j]*i]=0; break; }
    			mu[pri[j]*i]=-mu[i];	
    		}
    	}
    	for(int i=1;i<=M;i++)mu[i]+=mu[i-1];
    	int a,b,d;
    	while(n--){
    		a=read(),b=read(),d=read();
    		a/=d; b/=d;
    		int ans=0,lim=min(a,b);
    		for(int i=1,j=0;i<=lim;i=j+1){
    			j=min(a/(a/i),b/(b/i));
    			ans+=(mu[j]-mu[i-1])*(a/i)*(b/i);
    		}
    		printf("%d
    ",ans);
    	}
    }
    
  • 相关阅读:
    约瑟夫问题的解法集锦
    java调用com组件将office文件转换成pdf
    hdu(1069)——Monkey and Banana(LIS变形)
    Unix网络编程之环境搭建
    atitit. java queue 队列体系and自己定义基于数据库的队列总结o7t
    怎样使Dialog像Activity一样随心所欲的使用?
    获取全部分组中某列最大的行
    Class C++
    spring mvc +Mybatis3.1 整合的时候异常
    Linux 编译C++ 与 设置 Vim
  • 原文地址:https://www.cnblogs.com/naruto-mzx/p/12973840.html
Copyright © 2020-2023  润新知