唯一分解定理

Hanks 博士是 BT(Bio-Tech,生物技术)领域的知名专家,他的儿子名叫 Hankson。现在,刚刚放学回家的 Hankson 正在思考一个有趣的问题。

今天在课堂上,老师讲解了如何求两个正整数 c_1c 1 和 c_2c 2
的最大公约数和最小公倍数。现在 Hankson 认为自己已经熟练地掌握了这些知识,他开始思考一个“求公约数”和“求公倍数”之类问题的“逆问题”,这个问题是这样的:已知正整数 a_0,a_1,b_0,b_1a 0 ,a 1​ ,b 0​ ,b 1​ ,设某未知正整数x满足:xx 和 a_0a 0​ 的最大公约数是 a_1a 1
​ ;xx 和 b_0b 0​ 的最小公倍数是 b_1b 1 。
Hankson 的“逆问题”就是求出满足条件的正整数 xx 。但稍加思索之后,他发现这样的 xx 并不唯一,甚至可能不存在。因此他转而开始考虑如何求解满足条件的 xx 的个数。请你帮助他编程求解这个问题。
输入格式
第一行为一个正整数 nn ,表示有 nn 组输入数据。接下来的 nn 行每行一组输入数据,为四个正整数 a_0a
0​ ,a_1a
1​ ,b_0b
0​ ,b_1b 1​ ,每两个整数之间用一个空格隔开。输入数据保证 a_0a
0​ 能被 a_1a 1​ 整除,b_1b 1​ 能被 b_0b ​ 整除。

输出格式
对于每组数据:若不存在这样的 xx ,请输出 00;

若存在这样的 xx ,请输出满足条件的 xx 的个数;

数据范围
对于 50%50% 的数据,保证有 1 \le a_01≤a
0

,b_1b
1

,b_0b
0

,b_1 \le 10000b
1

≤10000 且 n \le 100n≤100。

对于 100%100% 的数据,保证有 1 \le a_01≤a
0

,b_1b
1

,b_0b
0

,b_1 \le 2,000,000,000b
1

≤2,000,000,000 且 n \le 2000n≤2000。

样例说明
第一组输入数据,xx 可以是 99、1818、3636、7272、144144、288288,共有 66 个。

第二组输入数据,xx 可以是 4848、17761776,共有 22 个。

输出时每行末尾的多余空格,不影响答案正确性

样例输入复制
2
41 1 96 288
95 1 37 1776
样例输出复制
6
2

解题思路:将a,b,c,d分解质因数存起来,用map存,然后枚举每个质数的t次,利用两个数质因子指数最小值等于约数的质因子指数,两个数的质因子的最大值等于最小公倍数的质因子指数,就好了。这题小技巧,用map<int,node> first代表质因子,node代表结构体里面存a,b,c,d

	#include<iostream>
	#include<algorithm>
	#include<cstdio>
	#include<cstring>
	#include<cmath>
	#include<map>
	#include<vector>
	#include<queue>
	#include<set>
	#define IL inline
	#define x first
	#define y second
	typedef long long ll;
	using namespace std;
	const	int N=1000010;
	struct node{
		int a;
		int b;
		int c;
		int d;
	};
	map<int,node>mp;
	int prime[N],cnt;
	bool st[N];
	void getprime(int n)
	{
		for(int i=2;i<=N;i++)
		{
			if(!st[i])
			prime[cnt++]=i;
			for(int j=0;prime[j]<=N/i;j++)
			{
				st[i*prime[j]]=true;
				if(i%prime[j]==0)
				break;
			}
		}
	}
	int tt[5];
	int main()
	{
		getprime(N);
		int n;
		cin>>n;
		while(n--)
		{
			mp.clear();
			int a,b,c,d;
			cin>>a>>b>>c>>d;
			tt[1]=a,tt[2]=b,tt[3]=c,tt[4]=d;
			for(int idx=1;idx<=4;idx++)	
		{
			int  cc=tt[idx];
			for(int i=0;i<cnt&&(ll)prime[i]*prime[i]<=cc;i++)
			{	
				if(cc%prime[i]==0)
				{
					int cnt=0;
					while(cc%prime[i]==0)
					{
						cc/=prime[i];
						cnt++;
					}
					if(idx==1)
					mp[prime[i]].a=cnt;
					if(idx==2)
					mp[prime[i]].b=cnt;
					if(idx==3)
					mp[prime[i]].c=cnt;
					if(idx==4)
					mp[prime[i]].d=cnt;
				}		
			}
	 	if(cc>=2)	//判断素数的情况 
			{
					if(idx==1)
					mp[cc].a=1;
					if(idx==2)
					mp[cc].b=1;
					if(idx==3)
					mp[cc].c=1;
					if(idx==4)
					mp[cc].d=1;			
			}
				}
			long long res=1;
			for(auto it:mp){
				int cnt=0;
			for(int j=0;j<=31;j++)
			{
				node t=it.second;
				int a=t.a,b=t.b,c=t.c,d=t.d;
				if(min(j,a)==b&&max(c,j)==d)
				cnt++;
			}
			res = res * cnt;
			}
			cout<<res<<endl;
		}
	    return 0;
	}
	
	

全部评论

相关推荐

最近群里有很多同学找我看简历,问问题,主要就是集中在明年三月份的暑期,我暑期还能进大厂嘛?我接下来该怎么做?对于我来说,我对于双非找实习的一个暴论就是title永远大于业务,你在大厂随随便便做点慢SQL治理加个索引,可能就能影响几千人,在小厂你从零到一搭建的系统可能只有几十个人在使用,量级是不一样的。对双非来说,最难的就是约面,怎么才能被大厂约面试?首先这需要一点运气,另外你也需要好的实习带给你的背书。有很多双非的同学在一些外包小厂待了四五个月,这样的产出有什么用呢?工厂的可视化大屏业务很广泛?产出无疑是重要的,但是得当你的实习公司到了一定的档次之后,比如你想走后端,那么中厂后端和大厂测开的选择,你可以选择中厂后端(注意,这里的中厂也得是一些人都知道的,比如哈啰,得物,b站之类,不是说人数超过500就叫中厂),只有这个时候你再去好好关注你的产出,要不就无脑大厂就完了。很多双非同学的误区就在这里,找到一份实习之后,就认为自己达到了阶段性的任务,根本不再投递简历,也不再提升自己,玩了几个月之后,美其名曰沉淀产出,真正的好产出能有多少呢?而实际上双非同学的第一份实习大部分都是工厂外包和政府外包!根本无产出可写😡😡😡!到了最后才发现晚了,所以对双非同学来说,不要放过任何一个从小到中,从中到大的机会,你得先有好的平台与title之后再考虑你的产出!因为那样你才将将能过了HR初筛!我认识一个双非同学,从浪潮到海康,每一段都呆不久,因为他在不断的投递和提升自己,最后去了美团,这才是双非应该做的,而我相信大部分的双非同学,在找到浪潮的那一刻就再也不会看八股,写算法,也不会打开ssob了,这才是你跟别人的差距。
迷茫的大四🐶:我也这样认为,title永远第一,只有名气大,才有人愿意了解你的简历
双非本科求职如何逆袭
点赞 评论 收藏
分享
2025-12-30 14:09
已编辑
北京交通大学 算法工程师
字节跳动 训练框架研发 (N+2) * (12 + 3) 硕士211
Crinton:训练框架遥遥领先
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务