LightOJ 1236 Pairs Forming LCM(唯一分解定理+素数筛)

本文深入探讨了求解特定整数下所有可能的最小公倍数(LCM)配对问题,利用质因数分解原理,阐述了一种高效算法。通过分析质因数的最大和最小指数,提出了一种计算配对数量的方法,并附带了C++实现代码。

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

Pairs Forming LCM

题解:考虑唯一分解定理:a=p1n1⋅p2n2...pknka = {p_1}^{n_1}\cdot {p_2}^{n_2}...{p_k}^{n_k}a=p1n1p2n2...pknkb=p1m1⋅p2m2...pkmkb = {p_1}^{m_1}\cdot {p_2}^{m_2}...{p_k}^{m_k}b=p1m1p2m2...pkmk
{lcm(a,b)=p1max(n1,m1)⋅p2max(n2,m2)...pkmax(nk,mk)gcd(a,b)=p1min(n1,m1)⋅p2min(n2,m2)...pkmin(nk,mk)\begin{cases}lcm(a,b) = {p_1}^{max(n_1,m_1)}\cdot {p_2}^{max(n_2,m_2)}...{p_k}^{max(n_k,m_k)}\\\\gcd(a,b) = {p_1}^{min(n_1,m_1)}\cdot {p_2}^{min(n_2,m_2)}...{p_k}^{min(n_k,m_k)}\end{cases}lcm(a,b)=p1max(n1,m1)p2max(n2,m2)...pkmax(nk,mk)gcd(a,b)=p1min(n1,m1)p2min(n2,m2)...pkmin(nk,mk)
所以我们考虑将nnn质因子分解n=p1e1⋅p2e2...pkekn = {p_1}^{e_1}\cdot {p_2}^{e_2}...{p_k}^{e_k}n=p1e1p2e2...pkek,有ei=max(ni,mi)e_i = max(n_i,m_i)ei=max(ni,mi)

对于i=p1n1⋅p2n2...pknki = {p_1}^{n_1}\cdot {p_2}^{n_2}...{p_k}^{n_k}i=p1n1p2n2...pknk时和j=p1m1⋅p2m2...pkmkj = {p_1}^{m_1}\cdot {p_2}^{m_2}...{p_k}^{m_k}j=p1m1p2m2...pkmk时的每一个质因子的指数我们都有max(ni,mi)+1max(n_i,m_i) + 1max(ni,mi)+1种取法,再除去i=x⋅pmi = x\cdot p^mi=xpmj=x⋅pnj= x\cdot p^nj=xpn的情况,因此总共就是2(ei+1)−12(e_i+1) - 12(ei+1)1种,然后又根据乘法原理有∏(2⋅ei+1)\prod{(2\cdot e_i+1)}(2ei+1),最后除去i>ji>ji>j和加上指数相等的情况,就有ans=∏2⋅ei+12+1ans = \frac{\prod{2\cdot e_i + 1}}{2} + 1ans=22ei+1+1

代码

#include<bits/stdc++.h>
typedef long long LL;
using namespace std;
const int N = 1E7+10, M = N / log(N) + N/10;
int prime[M], k;
bool vis[N];
void init()
{
	for(int i = 2; i < N; ++i) {
		if(vis[i] == 0)
			prime[k++] = i;
		for(int j = 2; j * i < N; ++j) {
			if(vis[i * j] == 0) 
				vis[i * j] = 1;
		}
	}
}

LL solve(LL n)
{
	LL t = n, ans = 1;
	for(int i = 0; i < k && prime[i] <= sqrt(t); ++i) {
		int cnt = 0;
		while(n % prime[i] == 0) {
			cnt++;
			n /= prime[i];
		}
		ans *= (2 * cnt + 1);
	}
	if(n > 1) ans *= (2 * 1 + 1);
	return ans / 2 + 1;
}

int main()
{
#ifndef ONLINE_JUDGE
    freopen("input.in","r",stdin);
#endif
	init();
	int T, t = 1;
	cin >> T;
	while(T--) {
		LL n;
		cin >> n;
		LL ans = solve(n);
		cout << "Case "<< t++ << ": " << ans << endl;
	}
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值