您的位置:首页 > 大数据 > 人工智能

LightOJ 1236 Pairs Forming LCM(算术基本定理)

2015-09-22 01:07 537 查看

LightOJ 1236 Pairs Forming LCM

题意:

[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 multiple
    return res;
}


在n<=10^14的情况下实现上述代码。

思路:

前些天还写过一题算术基本定理的题解,现在发现理解还不够透彻,比如这题按理来说应该是算术基本定理的模板题,但我居然没看出来。。

求约数,倍数,质因数,gcd,lcm,都应该想到这个定理的。

算术基本定理的内涵用一句话来概括就是:

一个数的每一个质因子的不同幂对应不同的因数。

而这题,我们假设( a , b ) = n ,那么:

n=pk11pk22⋯pkss,a=pd11pd22⋯pdss, b=pe11pe22⋯pess,可以确定max(ei,di)=ki,那么ki的组成就是ei与di中一个等于ki,另一个任取[0,ki]中的一个数,那么就有2(ki+1)种方案,实际上由于ei=di=ki方案会出现重叠,所以第i位方案数为2(ki+1)−1=2ki+1,有序对(a,b)方案数就是(2k1+1)(2k2+1)⋯(2ks+1),无序对(a,b)方案数就是:[(2k1+1)(2k2+1)⋯(2ks+1)+1]/2(n,n)已经只有一个,不会重复,所以+1。n=p_1^{k_1}p_2^{k_2}\cdots p_s^{k_s},\\
a=p_1^{d_1}p_2^{d_2}\cdots p_s^{d_s},\ b=p_1^{e_1}p_2^{e_2}\cdots p_s^{e_s},\\
可以确定\max(e_i,d_i)=k_i,\\
那么k_i的组成就是e_i与d_i中一个等于k_i,\\另一个任取[0,k_i]中的一个数,\\那么就有2(k_i+1)种方案,\\实际上由于e_i=d_i=k_i方案会出现重叠,\\所以第i位方案数为2(k_i+1)-1=2k_i+1,\\有序对(a,b)方案数就是(2k_1+1)(2k_2+1)\cdots(2k_s+1),\\无序对(a,b)方案数就是: \\ [(2k_1+1)(2k_2+1)\cdots(2k_s+1)+1]/2\\(n,n)已经只有一个,不会重复,所以+1。

代码:

[code]/*
* @author FreeWifi_novicer
* language : C++/C
*/
#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<string>
#include<map>
#include<set>
#include<vector>
#include<queue>

using namespace std;

#define clr( x , y ) memset(x,y,sizeof(x))
#define cls( x ) memset(x,0,sizeof(x))
#define pr( x ) cout << #x << " = " << x << endl 
#define pri( x ) cout << #x << " = " << x << " " 
#define test( t ) int t ; cin >> t ; int kase = 1 ; while( t-- )
#define out( kase ) printf( "Case %d: " , kase++ )
#define mp make_pair
#define pii pair<int,int>
#define pb push_back
typedef long long lint;
typedef long long ll;
typedef long long LL;

const int maxn = 1e7 + 50 ;
bool noprime[maxn+50] ;
vector<int>p ;
int getPrime(){
    cls( noprime ) ;
    p.clear() ;
    int m = (int)sqrt( maxn + 0.5 ) ;
    for( int i = 2 ; i <= m ; i++ )
        if( !noprime[i] )
            for( int j = i * i ; j <= maxn ; j += i )
                noprime[j] = true ;
    for( int i = 2 ; i <= maxn ; i++ )
        if( !noprime[i] ) p.pb( i ) ;
    return p.size() ;
}

int pf[100][2] ;
int getPrifac( lint n , int len ){
    int pos = 0 ;
    for( int i = 0 ; p[i] * p[i] <= n && i < len ; i++ ){
        if( n % p[i] == 0 ){
            pf[++pos][0] = p[i] ;
            pf[pos][1] = 0 ;
            while( n % p[i] == 0 ){
                pf[pos][1] ++ ;
                n /= p[i] ;
            }
        }
    }
    if( n > 1 ){
        pf[++pos][0] = n ;
        pf[pos][1] = 1 ;
    }
    return pos + 1 ;
}
lint calc( lint n , int len ){
    int num = getPrifac( n , len ) ;
    lint res = 1 ;
    for( int i = 0 ; i < num ; i++ )
        res *= ( pf[i][1] * 2 + 1 ) ;
    res ++ ;
    res /= 2 ;
    return res ;
}
int main(){
    //freopen("input.txt","r",stdin);
    int len = getPrime() ;
    test( t ){
        lint n ; cin >> n ;
        out( kase ) ;
        cout << calc( n , len ) << endl ;
    }
    return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: