zoukankan      html  css  js  c++  java
  • 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;
    }


  • 相关阅读:
    hduoj1285确定比赛名次
    HDU 1041 Computer Transformation 数学DP题解
    使用Git【转】
    Git-标签管理【转】
    Git-分支管理【转】
    Git-远程仓库【转】
    Git-时光穿梭【转】
    创建版本库【转】
    安装Git【转】
    Git简介【转】
  • 原文地址:https://www.cnblogs.com/mfrbuaa/p/5112035.html
Copyright © 2011-2022 走看看