2022“杭电杯”中国大学生算法设计超级联赛(9)

1008:Problem - 7240 (hdu.edu.cn)

题意:给定一个图,求图上两点之间的最短距离,两点之间的举例为两数的最大公约数

题解:二进制容斥原理+优化

两点若互质,则距离直接为1,且无更短或重复的路径了

若不互质或者gcd为2,则需要考虑范围内 与二者都互质的数有多少,互质的数即意味着 最大公约数为1,所以我们只需要排除掉两个数的质因子所构成的所有数即可,这里求两个数的质因子也需要注意,不能算重复,存储的时候需要记录是否重复,这里通过二进制容斥可以快速求解,一定数量的质因子所能构成的数的数目,但是这里容斥原理需要优化,不能一个二进制位一个二进制位的看该位是否为1,我们可以通过lowbit(int x)函数快速得到最低位1所构成的数的大小,还需要预处理2^n,快速求解该数所对应着第几位,然后通过容斥原理,我们便可筛选掉不互质的数了。‘

还有一点需要注意,若两数gcd为2,最后还需要考虑+1。

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N=10000100;
const int maxn=1e7;
int n,q;
const int mod=998244353;
const int NN=2e5+10;
int pre[NN];
set<int>st1,st2;
inline int lowbit(int x){//快速求解最低位1所对应的数字
	return x&(-x);
}
vector<int>ve;//存储两数的质因子,注意不能重复存,会浪费时间
inline void divide(int n) {//求解质因子
	for(int i=2; i<=n/i; i++) {
		if(n%i==0) {
			int s=0;
			while(n%i==0) {
				n/=i;
				s++;
			}
			if(!st1.count(i)) {//判重,若重复了,则不需要存了
				st1.insert(i);
				ve.push_back(i);
			}
		}
	}
	if(n>1) {
		if(!st1.count(n)) {
			st1.insert(n);
			ve.push_back(n);
		}
	}
}
int main() {
	for(int i=0;i<=15;i++) pre[1<<i]=i;//预处理2^n
	scanf("%d%d",&n,&q);
	for(int i=0; i<q; i++) {
		int n1,n2;
		scanf("%d%d",&n1,&n2);
		int e=__gcd(n1,n2);
		st1.clear();
		st2.clear();
		ve.clear();
		if(e==1) {//若两数互质
			printf("1 1\n");
		} else {
			LL sum=0;
			if(e==2)sum--;//考虑两数gcd==2的特殊情况
			divide(n1);//求解质因子
			divide(n2);
			int m=ve.size();
			for(int j=1; j<1<<m; j++) {//容斥原理 求解数量
				LL t=1;
				LL cnt=0;
				int w=j;
				int o=lowbit(w);
				while(o){//容斥原理优化 直接定位到最低位1,然后定位第二低位。。。。。通过减去最低位1实现
					int wei=pre[o];//通过预处理数组得到最低位1的位置
					cnt++;
					t*=ve[wei];
					if(t>n){
						t=-1;
						break;
					}
					w-=lowbit(w);//将第二低位1变为最低位1
					o=lowbit(w);
				}
				if(t!=-1) {
					if(cnt&1)sum+=n/t;//奇数+
					else sum-=n/t;//偶数-   --容斥原理
				}
			}
			printf("2 %d\n",(n-sum)%mod);
		}
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值