• hdu 2841 题解


    题目

    题意:就是问在一个$ n* m $的矩阵中站在 $ (0,0) $ 能看到几个整数点。

    很明显如果有两个平行向量 $ vec{a}=(x_1,y_1) $ ,$ vec{b}=(x_2,y_2) $ 那么很明显 $ (x_1,y_1) ,(x_2,y_2) $ 满足$ x_1=k* x_2 , y_1=k * y_2 $ 。那么两个点最多只能看到一个点,那么我们的目的就是找到有多少个点 $ (x,y) $ 中 $ x,y $ 互质 即 $ gcd(x,y)=1 $

    那么我们的问题就转变为 $ (1,n) $ 中有多少个数与 $ (1,m) $ 中的互质,我们假设从 $ (1,n) $ 中选出来一个数 $ i $ 那么我们怎么去判断互质的个数,进行素因子分解,则小于 $ m $ 能被 $ i $ 的素因子整除的数就不是与 $ i $互质的数,这是我们用容斥就可以求出总数。

    所以我们只要枚举 $ i $ 即可求出解,容斥怎么样加上有一个质因子的解的个数,减去有两个个质因子解的个数,再加上有三个质因子的解的个数....奇加偶减,就是如果一个数有 $ i $ 个质因数那么我们去判断 $ i $ 的奇偶性,如果是奇数就加上偶数减去,最后用n减去不是 $ i $ 互质的就是最后与 $ i $ 互质的个数了。

    代码

    #include<bits/stdc++.h>
    using namespace std;
    int T,n,m,k,prime[40];
    long long ans;
    int dfs(int n,int m){
    	k=0;
    	for(int i=2;i*i<=m;++i){
    		if(m%i) continue;
    		while(m%i==0) m/=i;
    		prime[k++]=i;
    	}if(m!=1) prime[k++]=m;
    	int add=0;
    	for(int i=1;i<(1<<k);++i){//分解出来k-1个质数,枚举所有可能的组合情况 2^(k-1)
    		int tmp=1,cnt=0;
    		for(int j=0;j<k;++j){
    			if(!((i>>j)&1)) continue;//没有选这个数
    			tmp*=prime[j];
    			++cnt;
    		}
    		if(cnt&1) add+=n/tmp;//奇加偶减
    		else add-=n/tmp;
    	}
    	return n-add;//减去不满足的就是满足的
    }
    int main(){
    	scanf("%d",&T);
    	while(T--){
    		ans=0;
    		scanf("%d %d",&n,&m);
    		for(int i=1;i<=n;++i){//固定m枚举i
    			ans+=dfs(m,i);
    		}printf("%lld
    ",ans);
    	}
    	return 0;
    }
    
  • 相关阅读:
    一句话概括下spring框架及spring cloud框架主要组件
    服务注册与发现
    微服务API Gateway
    微服务分布式事务的一些思考
    微服务框架的存储架构
    轻量级微服务框架的通信架构
    基于Docker的负载均衡和服务发现
    测试一下标签
    让360安全浏览器默认使用谷歌内核
    schema中字段类型的定义
  • 原文地址:https://www.cnblogs.com/donkey2603089141/p/11829302.html
Copyright © 2020-2023  润新知