1236 - Pairs Forming LCM (唯一分解定理加组合数学)

本文介绍了如何运用唯一分解定理解决一道关于求解形成最大公约数(LCM)配对的数学问题。首先对n进行素因子分解,然后分析当Lcm(a,b)=n时a和b的素因子指数关系。每个素因子的指数c可以生成2*c+1种配对方式,考虑到有序性,最后结果需除以2并加1。" 129098031,17386950,Java实现万年历打印,"['java', 'java-ee']
摘要由CSDN通过智能技术生成

一、题目链接:传送门

二、题解: <1> 先对n进行素因子分解,时间复杂度近似sqrt(n) / k,k为一个常数。

                      <2> 假设 n = a1^p1 * a2 ^ p2 * a3 ^ p3 * ... * an ^ pn。 (ai为素因子,pi为素因子的指数)

                      <3> 假设Lcm(a,b) = n,则对于每一个素因子ai,a中的pi,与b中的pi,至少有一个为ai的指数。

      <4> 所以对于n中的每一个素因子的指数c,我们都可以分解成一对(a,b),且max(a,b) = c,这样的分法有2 * c + 1中,

        对于其它的素因子同理,因为Lcm对是有序的,所以最后的结果要除以2,再加1,因为(n,n)我们只算了一次。

三、AC代码如下:

/* ***********************************************
Author        :xdlove
Created Time  :2015年09月03日 星期四 13时02分46秒
File Name     :a.cpp
 ************************************************ */

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <memory.h>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <string>
#include <math.h>
#include <stdlib.h>
#include <time.h>

using namespace std;
typedef long long ll;
const int MAXN = 1e7;
bool check[MAXN + 2];
int prime[700000];
int e[700000];

void getprime()
{
    memset(check,false,sizeof(check));
    for(int i = 2; i <= MAXN; i++)
    {
        if(!check[i]) prime[++prime[0]] = i;
        for(int j = 1; j <= prime[0]; j++)
        {
            if(prime[j] > MAXN / i) break;
            check[i * prime[j]] = true;
            if(i % prime[j] == 0) break;
        }
    }
}

int main()
{
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    //srand(time(NULL));
    getprime();
    int T,cnt = 0;
    ll n;
    cin>>T;
    while(T--)
    {
        scanf("%lld",&n);
        memset(e,0,sizeof(e));
        for(int i = 1; i <= prime[0]; i++)
        {
            if(prime[i] > n / prime[i]) break;
            while(n % prime[i] == 0)
            {
                e[i]++;
                n /= prime[i];
            }
            if(n == 1) break;
        }
        ll ans = 1;
        for(int i = 1; i <= prime[0]; i++)
            if(e[i]) ans *= 2 * e[i] + 1;
        if(n != 1) ans *= 3;
        printf("Case %d: %lld\n",++cnt,ans/2 + 1);
    }
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值