B - Pairs Forming LCM——(LightOJ 1236)

传送门
password:nefu

Find the result of the following code:

long long pairsFormLCM( int n ) {
    long long res = 0;
    for( int i = 1; i <= n; i++ )
        for( int j = i; j <= n; j++ )
           if( lcm(i, j) == n ) res++; // lcm means least common multiple0A return res;
}

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).

Input

Input starts with an integer T (≤ 200), denoting the number of test cases.

Each case starts with a line containing an integer n (1 ≤ n ≤ 1014).

Output

For each case, print the case number and the value returned by the function ‘pairsFormLCM(n)’.

Sample Input

15

2

3

4

6

8

10

12

15

18

20

21

24

25

27

29

Sample Output

Case 1: 2

Case 2: 2

Case 3: 3

Case 4: 5

Case 5: 4

Case 6: 5

Case 7: 8

Case 8: 5

Case 9: 8

Case 10: 8

Case 11: 5

Case 12: 11

Case 13: 3

Case 14: 4

Case 15: 2

题目大意:
首先给出一个T,表示T组数据,然后给出一个m,就是根据那段代码求<=m的两个数的LCM 的个数
解题思路:
根据算术基本定理(唯一分解定理),LCM(A,B)== m;
n = p1^e1 * p2^e2 * … *pk^ek;
A = p1^a1 * p2^a2 * … *pk^ak;
B = p1^b1 * p2^b2 * … *pk^bk;
要是想 LCM(A,B)== m,
只需要:
e1 = max(a1,b1);
e2 = max(a2,b2);

ek = max(ak,bk)
从[0,ei]中取一个数,那么就有2(ei+1)种方法可以取,
但是当ai = bi = ei 的时候就得-1
所以需要的次数时2*ei+1,
有序对(a,b)方案数就是(2e1+1)(2e2+1)⋯(2ek+1),
无序对(a,b)方案数就是,判断奇偶 /2 就行,
然后需要做的就是写程序啦, 首先要做的是素数筛选,
然后是素因子分解,最后将上述所用的方法用程序实现,
注意数据范围是10^7
上代码:

/** 唯一分解定理 **/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <vector>
#include <queue>
#include <algorithm>
#include <set>
using namespace std;

#define MM(a) memset(a,0,sizeof(a))

typedef long long LL;
typedef unsigned long long ULL;
const int MAXN = 1e7+5;
const int mod = 1000000007;
const double eps = 1e-7;
bool prime[MAXN];
LL p[MAXN/10],k;
///素数筛选
void isprime()
{
    k = 0;
    MM(prime);
    for(LL i=2; i<MAXN; i++)
    {
        if(!prime[i])
        {
            p[k++] = i;
            for(LL j=i*i; j<MAXN; j+=i)
                prime[j] = 1;
        }
    }
}
LL fac[MAXN/100], num[MAXN/100], cnt;
///分解素因子算法
void Dec(LL x)
{
    MM(num);
    cnt = 0;
    for(LL i=0; p[i]*p[i]<=x&&i<k; i++)
    {
        if(x%p[i] == 0)
        {
            fac[cnt] = p[i];
            while(x%p[i] == 0)
            {
                num[cnt]++;
                x /= p[i];
            }
            cnt++;
        }
    }
    if(x > 1)
    {
        fac[cnt] = x;
        num[cnt++] = 1;
    }
}

int main()
{
    int T;
    isprime();
    cin>>T;
    for(int cas=1; cas<=T; cas++)
    {
        LL m;
        cin>>m;
        Dec(m);
        LL ret = 1;
        for(int i=0; i<cnt; i++)
            ret *= (num[i]*2+1);
        ///cout<<num[i]<<" ";
        if(ret & 1)
            ret = (ret>>1)+1;
        else
            ret>>=1;
        printf("Case %d: %lld\n",cas,ret);
    }
    return 0;
}

你可能感兴趣的:(数论,素因子分解)