Pairs Forming LCM

题目

Find the result of the following code:
图片说明
A straight forward implementation of the code may time out. If you analyze the code, you will find that the code actually counts the number of pairs (i, j) for which lcm(i, j) = n and (i ≤ j).
题意就是,这个函数的复杂度很高,让你写出一个程序来实现同样的功能。

分析

n 是a,b 的最小公倍数
我们可以把a,b进行质因数分解



这里,如果有一方没有另一方的某个质因数p,就相当于,这样便于统一形式
所以:



而这里lcm(a,b) = n

计算每一项质因数的幂的方案数:

现在,对于每一项质因数的幂,需要a,b某一方也有,而另一方可以是(共ei+1)种,然后就是,之所以减一,是因为,当时,选谁都一样,不需要

计算总方案数

对于每一种方案数要进行相乘,但是现在题目要求,所以我们要将总方案数/2+1,加一是因为如果直接除以2,其中有一种方案 a是等于b的,所以除多了,需要加上1

AC代码

#include <iostream>
#include <algorithm>
#include <cmath>
#include <stdio.h>
using namespace std;
const int maxn = 1e7+10;
typedef long long ll;

ll T,N;
ll P[1000010],tail; //1e7之前只有不到1e6的质数,所以这里1e6的空间就够了
bool vis[maxn];//判断是否是质数需要1e7的空间

void init(){
    ll len = (ll)sqrt(maxn)+1;
    for(int i = 2;i<=len;i++){
        if(!vis[i]){
            for(int j = i*i;j<maxn;j+=i){
                vis[j] = true;
            }
        }
    }
    for(int i = 2;i<maxn;i++){
        if(!vis[i]) P[tail++] = i;
    }
}

ll solve(ll x){
    ll sum = 1;
    for(int i = 0;i<tail && P[i]*P[i]<=x;i++){
        if(x%P[i] == 0){
            int cnt = 0;
            while(x%P[i] == 0){
                cnt++;
                x/=P[i];
            }
            sum *= 2*(cnt+1)-1;
        }
    }
    if(x>1) sum *= 2*(1+1)-1;
    return sum/2+1;
}

int main(){
    init();
    cin>>T;
    int kase = 0;
    while(T--){
        scanf("%lld",&N);
        printf("Case %d: %lld\n",++kase,solve(N));
    }
    return 0;
}