呃,有好久没写博了,很无奈呢,每次做完题总是会忘了这最后一步。。。。
这题是上次比赛的一道题,比赛中就认为这题有技巧,其实在比赛中XH就找到了结论,但是由于当时我们俩都没接触过快速判素和快速求质因子的方法,也就是Miller_Rabbin和Pollard_Rho方法,所以尝试了几次打表,结果没过,然后就不了了之了。赛后看了解题报告,知道思路没错,有用打表的方法做了两遍,还是原样,题解中说用到了Pallard_Rab求质因子,所以就上网搜搜了,然后直到今天才做这题。
题意:求出N的所有因子,然后选出尽可能多的元素,是的选出的元素两两互质,求出最长的长度和这些元素的最大和。
思路:为了尽可能多的选出,每个L的质因子应当只包含N的一个质因子,L是一个质因子的整数次,所以K的值就是N中不同质因子的个数, 要想和最大,那么使得每个L最大,只要使得质因子的指数最大即可。
再来说说上面的两个定理:
Miller_Rabbin:是根据费马小定理而推出的一种有随机数来判断一个数是否是质数,原理我看了一篇百度贴吧里的文章明白的,给出网址,有兴趣可以去看看。
http://tieba.baidu.com/p/129366421
Pollard_Rho:我觉得想弄懂这个算法,还是要看算法导论的,第三十一章的整数的因子分解。
代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <iostream> #include <algorithm> #include <map> #include <math.h> #define N 205 using namespace std ; typedef long long ll ; ll f[N] , n ; int num ; //求x,y的最大公约数 ll gcd( ll x , ll y ) { if ( !y ) return x ; else return gcd( y , x % y ) ; } //求a*b ll Multip ( ll a , ll b , ll n ) { ll k = a % n ; ll res = 0 ; while( b ) { if ( b & 1 ) { res += k ; if ( res > n ) res -= n ; } k <<= 1 ; if ( k > n ) k -= n ; b >>= 1 ; } return res ; } //求(a^b)mod n ll Exp_mod( ll a , ll b , ll n ) { ll s = 1 ; while( b ) { if ( b & 1 ) s = Multip( s , a , n ); a = Multip ( a , a , n ); b >>= 1; } return s ; } //判断n是否是素数,c代表测试的次数 bool Miller_Rabbin( ll n , ll c ) { if ( n == 2 ) return true ; if ( n < 2 || !( n & 1)) return false ; int t = 0 ; ll x , y , a ; ll m = n - 1 ; while( m % 2 == 0 ) { t++ ; m /= 2 ; } srand( 100 ); for ( int i = 0 ; i < c ; i++ ) { a = rand() % ( n - 1 ) + 1 ; x = Exp_mod( a , m , n ); for ( int j = 0 ; j < t ; j++ ) { y = Multip( x , x ,n ); if ( y == 1 && x != 1 && x != n - 1 ) return false ; x = y ; } if ( y != 1 ) return false ; } return true ; } //求n的质因子 ll Pallard_Rab( ll n , ll c ) { int i = 1 , k = 2 ; ll x , y , d ; x = y = rand() % ( n -1 ) + 1 ; while( 1 ) { i++ ; x = ( Multip( x , x , n ) + c ) % n ; d = gcd ( ( x - y + n ) % n , n ); if ( d > 1 && d < n ) return d ; if ( x == y ) return n ; if ( i == k ) { k <<= 1 ; y = x ; } } } //求出N的所有质因子,并记录 void Find_factors( ll n , ll c ) { if ( n == 1 ) return ; if ( Miller_Rabbin( n , 6 )) { f[num++] = n ; return ; } ll p = n ; ll k = c ; while( p >= n ) p = Pallard_Rab( p , c-- ); Find_factors( p , k ); Find_factors( n / p , k ); } // a^b ll powx( ll a , ll b ) { ll s = 1 ; for ( int i = 0 ; i < b ; i++ ) s *= a ; return s ; } int main() { int cas , i ; cin>>cas ; while( cas-- ) { cin>>n ; num = 0 ; Find_factors( n , 120 ); map<ll , int>ms ; for ( i = 0 ; i < num ; i++ ) ms[f[i]]++ ; int s = ms.size(); if ( s == 1 ) { cout<<s<<" "<<( n / f[0] )<<endl ; } else { ll sum = 0 ; map<ll , int>::iterator it ; for ( it = ms.begin() ; it != ms.end() ; it++ ) { sum += powx ( it->first , it->second) ; } cout<<s<<" "<<sum<<endl; } } return 0 ; }