hdu 4344 Mark the Rope(Miller_Rabbin+Pollard_Rho)

呃,有好久没写博了,很无奈呢,每次做完题总是会忘了这最后一步。。。。

这题是上次比赛的一道题,比赛中就认为这题有技巧,其实在比赛中XH就找到了结论,但是由于当时我们俩都没接触过快速判素和快速求质因子的方法,也就是Miller_Rabbin和Pollard_Rho方法,所以尝试了几次打表,结果没过,然后就不了了之了。赛后看了解题报告,知道思路没错,有用打表的方法做了两遍,还是原样,题解中说用到了Pallard_Rab求质因子,所以就上网搜搜了,然后直到今天才做这题。

题意:求出N的所有因子,然后选出尽可能多的元素,是的选出的元素两两互质,求出最长的长度和这些元素的最大和。

思路:为了尽可能多的选出,每个L的质因子应当只包含N的一个质因子,L是一个质因子的整数次,所以K的值就是N中不同质因子的个数, 要想和最大,那么使得每个L最大,只要使得质因子的指数最大即可。

再来说说上面的两个定理:

Miller_Rabbin:是根据费马小定理而推出的一种有随机数来判断一个数是否是质数,原理我看了一篇百度贴吧里的文章明白的,给出网址,有兴趣可以去看看。

http://tieba.baidu.com/p/129366421

Pollard_Rho:我觉得想弄懂这个算法,还是要看算法导论的,第三十一章的整数的因子分解。

代码:

View Code
#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 ;
}

 

转载于:https://www.cnblogs.com/misty1/archive/2012/08/10/2633077.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值