数论(分解质因数 + 组合计数) - Pairs Forming LCM - LightOJ 1236

数论(分解质因数 + 组合计数) - Pairs Forming LCM - LightOJ 1236

题意:
在这里插入图片描述

i j n ( i , j ) i j 计算满足i和j的最小公倍数为n的不同数对(i,j)的个数,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 i m e   l i m i t 2000 m s M e m o r y   l i m i t 32768 k B Time\ limit:2000 ms,Memory \ limit:32768 kB


分析:

n a b 假设n是a和b的最小公倍数,设:

a = p 1 a 1 × p 2 a 2 × . . . × p n a n a=p_1^{a_1}×p_2^{a_2}×...×p_n^{a_n}

b = p 1 b 1 × p 2 b 2 × . . . × p n b n b=p_1^{b_1}×p_2^{b_2}×...×p_n^{b_n}

a i , b i 0 1 i n a_i,b_i≥0,1≤i≤n。

则:

g c d ( a , b ) = p 1 m i n ( a 1 , b 1 ) × p 2 m i n ( a 2 , b 2 ) × . . . × p n m i n ( a n , b n ) gcd(a,b)=p_1^{min(a_1,b_1)}×p_2^{min(a_2,b_2)}×...×p_n^{min(a_n,b_n)}

l c m ( a , b ) = p 1 m a x ( a 1 , b 1 ) × p 2 m a x ( a 2 , b 2 ) × . . . × p n m a x ( a n , b n ) lcm(a,b)=p_1^{max(a_1,b_1)}×p_2^{max(a_2,b_2)}×...×p_n^{max(a_n,b_n)}

m a x ( a i , b i ) = e i 记max(a_i,b_i)=e_i,

n = p 1 e 1 × p 2 e 2 × . . . × p n e n 则n=p_1^{e_1}×p_2^{e_2}×...×p_n^{e_n}

( a , b ) p i 要求不同数对(a,b)的数量,对于每一个素因子p_i,

a p i e i b p 0 , p 1 , . . . , p e i e i + 1 在a中取p_i^{e_i},在b中可取p^{0},p^1,...,p^{e_i},共e_i+1种不同取值,

C 2 1 × ( e i + 1 ) 1 1 a i = b i = e i 反过同理,故方案数为C_2^1×(e_i+1)-1,-1是为了去掉重复统计的a_i=b_i=e_i的情况。

: s u m = i = 1 n 2 × ( e i + 1 ) 1 那么总的方案数为:sum=\prod_{i=1}^n2×(e_i+1)-1

a b 2 另外,本题要求a≤b,因此总方案数还需除2。

a i = b i = e i 2 1 需注意a_i=b_i=e_i的情况我们只统计了一次,除2后由于下取整的缘故,还要再累加上1。

具体细节:

n n ①、筛出\sqrt{n}内的质数,然后对输入的n进行质因数分解。

1 0 7 7 × 1 0 5 7 × 1 0 5 \qquad注意空间不能超,10^7内的质数不超过7×10^5,数组开7×10^5足够。

n ②、对输入的每个n进行质因数分解,计算每个质因数的质数,根据乘法原理进行计数。

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>

#define ll long long

using namespace std;

const int N=1e7+10;

int primes[700000],cnt;
bool st[N];

void get_prime(int n)
{
    for(int i=2;i<=n;i++)
    {
        if(!st[i]) primes[cnt++]=i;
        for(int j=0;primes[j]*i<=n;j++)
        {
            st[primes[j]*i]=true;
            if(i%primes[j]==0) break;
        }
    }
}

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

int main()     
{
    get_prime(N-1);
    
    int T; cin>>T;
    for(int t=1;t<=T;t++)
    {
        ll n; cin>>n;
        printf("Case %d: %lld\n",t,solve(n));
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/njuptACMcxk/article/details/107739057
今日推荐