UVA 10892 LCM Cardinality(数论 质因数分解)

LCM Cardinality
Input: 
Standard Input

Output: Standard Output

Time Limit: 2 Seconds

A pair of numbers has a unique LCM but a single number can be the LCM of more than one possible pairs. For example 12 is the LCM of (1, 12)(2, 12)(3,4) etc. For a given positive integer N, the number of different integer pairs with LCM is equal to N can be called the LCMcardinality of that number N. In this problem your job is to find out the LCM cardinality of a number.

Input

The input file contains at most 101 lines of inputs. Each line contains an integer N (0<N<=2*109). Input is terminated by a line containing a single zero. This line should not be processed.

Output

For each line of input except the last one produce one line of output. This line contains two integers N and C. Here N is the input number and Cis its cardinality. These two numbers are separated by a single space.

Sample Input                             Output for Sample Input

2                                                          
12
24
101101291
0

2 2

12 8

24 11

10110129


题意:给出a和b的最小公倍数N。找出符合条件的a、b有多少对。

分析:1. 设n = LCM(a,b) = (p1^r1) * (p2^r2) * (p3^r3) … (pm^rm)
   又设a=(p1^a1) * (p2^a2) * (p3^a3) … (pm^am),
   b=(p1^b1) * (p2^b2) * (p3^b3)… (pm^bm)
   由LCM的定义有ri = max{ai, bi}
   所以对于每一个ri,ai和bi中至少有一个要取ri
2. 对于ai取ri的情况,bi能够取[0,ri-1]的随意整数,这有ri种情况;
   bi取ri的情况相同是ri种 。
   最后加上ai和bi都取ri的情况,共同拥有(2*ri+1)种情况
3. 由于这么考虑把(a,b)和(b,a)算反复了,但(n,n)的情况仅仅算了一遍。所以最后要ans= (ans+1)/2=ans/2+1(由于ans是奇数)
4. 优化:仅仅考虑√n范围内的质数,但这样会存在漏掉一个大质数的情况(比方n=2*101) 。这个大质数的幂次仅仅能为1(即少算了一个*(2*1+1)),所以在这样的情况发生时要补上ans*=3,写成 位运算就是ans+=ans<<1。

#include <cstdio>
#include <cmath>

int n;

void get_ans() {
    int tmp = n;
    int m = (int)sqrt(n + 0.5);
    long long ans = 1;
    for(int i = 2; i <= m; i += 2) {
        if(n % i == 0) {
            int cnt = 0;
            while(n % i == 0) {
                n /= i;
                cnt++;
            }
            ans *= (cnt << 1) + 1;
        }
        if(i == 2) i--;
    }
    if(n > 1) ans += (ans<<1);
    ans = (ans >> 1) + 1;
    printf("%d %lld
", tmp, ans);
}

int main() {
    while(~scanf("%d", &n) && n) {
        get_ans();
    }
    return 0;
}


原文地址:https://www.cnblogs.com/mfrbuaa/p/5112035.html