AtCoder 259E LCM

文章提出了一个数学问题,涉及将整数n个数表示为质因数的唯一分解形式,并探讨当将其中一个数改为1时,所有可能的lcm(最小公倍数)的变化。解决方案主要关注质因数的最高次幂,指出只有当某质因数的最高次幂在数列中独一无二时,改变该数才会对lcm产生影响。通过维护每个质因数的最高次幂和出现次数,可以计算出不同lcm的数量。最后,使用集合存储不同乘积,集合的大小即为答案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题意:

以唯一分解形式给出 n n n个数:
a i = p i , 1 e i , 1 p i , 2 e i , 2 . . . p i , t e i , t a_{i}=p_{i,1}^{e_{i,1}}p_{i,2}^{e_{i,2}}...p_{i,t}^{e_{i,t}} ai=pi,1ei,1pi,2ei,2...pi,tei,t
现在可以将某个数改为 1 1 1,求所有改法中,有多少个不同的 l c m ( a 1 , a 2 , . . . , a n ) lcm(a_{1},a_{2},...,a_{n}) lcm(a1,a2,...,an)

Solution:

由于涉及 l c m lcm lcm,不妨将各个数改写成这样的形式
a 1 = 2 e 1 , 1 3 e 1 , 2 5 e 1 , 3 . . . . . . . a n = 2 e n , 1 3 e n , 2 5 e n , 3 . . . . a_{1}=2^{e_{1,1}}3^{e_{1,2}}5^{e_{1,3}}.... \\ ... \\ a_{n}=2^{e_{n,1}}3^{e_{n,2}}5^{e_{n,3}}.... a1=2e1,13e1,25e1,3.......an=2en,13en,25en,3....
那么
l c m ( a 1 , a 2 , . . . , a n ) = 2 m a x { e 1 , 1 , e 2 , 1 , . . . , e n , 1 } 3 m a x { e 1 , 2 , e 2 , 2 , . . . , e n , 2 } . . . lcm(a_{1},a_{2},...,a_{n})=2^{max\{e_{1,1},e_{2,1},...,e_{n,1}\}}3^{max\{e_{1,2},e_{2,2},...,e_{n,2}\}}... lcm(a1,a2,...,an)=2max{e1,1,e2,1,...,en,1}3max{e1,2,e2,2,...,en,2}...
考虑删掉一个数的影响,即将某个数 a k a_{k} ak设为1
a k = 2 0 3 0 5 0 . . . . a_{k}=2^{0}3^{0}5^{0}.... ak=203050....
对于一个质数底 p k , i p_{k,i} pk,i,如果他的幂是 n n n个数里同底的唯一最高次的话,删去他才会对 l c m lcm lcm有影响,如果两个数的唯一最高次的底的构成是一样的,那么对这两个数的操作是等价的,于是考虑存在多少个不同的构成的数。

由于唯一分解内,不同的构成的乘积一定不同,于是可以用他们的乘积代表他们的构成,用一个map来指示这个底的最高次

底x的最高次幂=map1[x]
底x有多少个最高次幂=tot[x]

把他们的乘积加入set后,set的大小就是答案

#include<iostream>
#include<vector>
#include<cstdlib>
#include<numeric>
#include<unistd.h>
#include<queue>
#include<algorithm>
#include<cmath>
#include<cstdio>
#include<set>
#include<map>
#include<stack>
#include<utility>
#include<cctype>
#include<cassert>
#include<thread>
#include<bitset>
using namespace std;

using ll=long long;
const int N=2e5+5,inf=0x3fffffff;
const long long INF=0x3fffffffffffffff,mod=1e11+7;

int n;
vector<int>p[N],e[N];
map<int,int>map1,tot;

int main() {
	#ifdef stdjudge
		freopen("in.txt","r",stdin);
		auto TimeFlagFirst=clock();
	#endif

	std::ios::sync_with_stdio(false);
	std::cin.tie(nullptr);

	cin>>n;
	for(int i=1;i<=n;i++) {
		int t; cin>>t;
		while(t--) {
			int pp,ee; cin>>pp>>ee;
			if(!map1.count(pp)) map1[pp]=ee,tot[pp]=1;
			else if(ee>map1[pp]) map1[pp]=ee,tot[pp]=1;
			else if(ee==map1[pp]) tot[pp]++;
			p[i].emplace_back(pp);
			e[i].emplace_back(ee);
		}
	}

	set<ll>set1;

	for(int i=1;i<=n;i++) {
		ll val=1;
		for(int j=0;j<p[i].size();j++) {
			if(e[i][j]==map1[p[i][j]]&&tot[p[i][j]]==1) val=val*p[i][j]%mod;
		}
		set1.insert(val);
	}

	cout<<set1.size()<<endl;

	#ifdef stdjudge
		freopen("CON","r",stdin);
		std::cout<<std::endl<<"耗时:"<<std::clock()-TimeFlagFirst<<"ms"<<std::endl;
		std::cout<<std::flush;
		system("pause");
	#endif
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值