【唯一分解定理】LightOJ - 1236 Pairs Forming LCM

本文探讨了利用唯一分解定理解决求特定条件下两数最小公倍数等于给定数的方案数问题。通过分解质因数并计算组合数,提供了一种高效求解策略。

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

【唯一分解定理】LightOJ - 1236 Pairs Forming LCM

题意:
求1=<i<=n,1<=j<=n,lcm(i,j)=n的方案数。

思路:
n = p1 ^ e1 * p2 ^ e2 *…*pn ^ en

for i in range(1,n): ei 从0取到ei的所有组合
必能包含所有n的因子。
现在取n的两个因子a,b
a=p1 ^ a1 * p2 ^ a2 *…*pn ^ an
b=p1 ^ b1 * p2 ^ b2 *…*pn ^ bn
gcd(a,b)=p1 ^ min(a1,b1) * p2 ^ min(a2,b2) *…*pn ^ min(an,bn)
lcm(a,b)=p1 ^ max(a1,b1) * p2 ^ max(a2,b2) *…*pn ^ max(an,bn)
先对n素因子分解,n = p1 ^ e1 * p2 ^ e2 *…*pk ^ ek,
lcm(a,b)=p1 ^ max(a1,b1) * p2 ^ max(a2,b2) *…*pk ^ max(ak,bk)
所以,当lcm(a,b)==n时,max(a1,b1)==e1,max(a2,b2)==e2,…max(ak,bk)==ek当ai==ei时,bi可取[0,ei]中的所有数有ei+1种情况,bi==ei时同理。那么就有2(ei+1)种取法,但是当ai=bi=ei时有重复,所以取法数为2(ei+1)−1=2ei+1。除了(n,n)所有的情况都出现了两次那么满足a&lt;=b的有(2ei+1))/2+1个lcm(a,b)==n时,max(a1,b1)==e1,max(a2,b2)==e2,…max(ak,bk)==ek 当ai == ei时,bi可取 [0, ei] 中的所有数 有 ei+1 种情况,bi==ei时同理。 那么就有2(ei+1)种取法,但是当ai = bi = ei 时有重复,所以取法数为2(ei+1)-1=2ei+1。 除了 (n, n) 所有的情况都出现了两次 那么满足a&lt;=b的有 (2ei + 1)) / 2 + 1 个lcm(a,b)==nmax(a1,b1)==e1,max(a2,b2)==e2,max(ak,bk)==ekai==eibi[0,ei]ei+1bi==ei2(ei+1),ai=bi=ei2(ei+1)1=2ei+1(n,n)a<=b(2ei+1))/2+1

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
typedef long long LL;
const int N=1e7+5;
const int NN=1e6;
unsigned int prime[NN],cnt;           //prime[N]会MLE
bool vis[N];

void is_prime()
{
    cnt=0;
    memset(vis,0,sizeof(vis));
    for(int i=2;i<N;i++)
    {
        if(!vis[i])
        {
            prime[cnt++]=i;
            for(int j=i+i;j<N;j+=i)
            {
                vis[j]=1;
            }
        }
    }
}

int main()
{
    is_prime();
    int t;
    cin>>t;
    for(int kase=1;kase<=t;kase++)
    {
        LL n;
        cin>>n;
        int ans=1;
        for(int i=0;i<cnt&&prime[i]*prime[i]<=n;i++)
        {
            if(n%prime[i]==0)
            {
                int e=0;
                while(n%prime[i]==0)
                {
                    n/=prime[i];
                    e++;
                }
                ans*=(2*e+1);
            }
        }
        if(n>1)
            ans*=(2*1+1);
        printf("Case %d: %d\n",kase,(ans+1)/2);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值