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)

输入:

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 ≤ 10^{14}).

输出:

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

样例输入:

15

2

3

4

6

8

10

12

15

18

20

21

24

25

27

29

样例输出:

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

 

这个题是给出一个数n,求有多少对a,b(a,b<=n)(a<b)的最小公倍数是n。
素因子分解:n = p1 ^ e1 * p2 ^ e2 *..........*pn ^ en

a=p1 ^ a1 * p2 ^ a2 *..........*pn ^ an

b=p1 ^ b1 * p2 ^ b2 *..........*pn ^ bn

lcm(a,b)=p1 ^ max(a1,b1) * p2 ^ max(a2,b2) *..........*pn ^ max(an,bn)

a,b有两种情况:

a= p1^a1,那么b=p1^m,(m属于[0,a1]),这样一共有a1+1种;

b= p1^a1,那么a=p1^n,(n属于[0,a1])这样一共有a1+1种。

所以总共有2*(a1+1)种,当m=n时,情况一样,所以要减去一种,所以一共2a1+1种

当n = p1^a1*p2^a2*p3^a3*...*ps^as时总情况ans = (2*a1+1)*(2*a2+1)*(2*a3+1)*...*(2*as+1);

这里的ans是包括(a,b),(b,a)的,题中说的是要求(a<=b)的,所以要除以2.最后还有一种(n,n)的情况要加上。

代码:

#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cstring>
using namespace std;
const int  maxn= 1e7;
const int x=1e6;
#define ll long long
int prime[x];//用来保存素数,这里不能用maxn,否则会MLE
bool vis[maxn];
int cnt;
void isprime()
{
    cnt=0;
    memset(vis,0,sizeof(vis));
    for(int i=2;i<maxn;i++)
    {
        if(!vis[i])
        {
            prime[cnt++]=i;
            for(int j=i+i;j<maxn;j+=i)
            {
                vis[j]=1;
            }
        }
    }
}
int main()
{
    isprime();
    int t;
    ll n;
    cin>>t;
    int res=1;
    while(t--)
    {
        scanf("%lld",&n);
        int ans=1;
        for(int i=0;i<cnt&&prime[i]*prime[i]<=n;i++)
        {
            if(n%prime[i]==0)//这里用来求这个素因子出现的次数,能除尽一次次数就加1,只能不除
                             //尽为止,就是出现的次数
            {
                int num=0;
                while(n%prime[i]==0)
                {
                    n/=prime[i];
                    num++;
                }
                ans*=(2*num+1);
            }
        }
        if(n>1)//当经过上面的for循环,n一定是一个素数了,这时候还有他本身没有进行公式运算
               //而且它本身只出现过一次,所以再次使用公式
            ans*=(2*1+1);
        printf("Case %d: %d\n",res++,ans/2+1);//最后除以2,再加上最后一种(n,n)的情况
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/zhangjinlei321/article/details/82192665
今日推荐