hdu - 4344 - Mark the Rope - 大数分解

来源:互联网 发布:泛鹏天地知乎 编辑:程序博客网 时间:2024/05/17 08:02

http://acm.hdu.edu.cn/showproblem.php?pid=4344

注意选的间隔长度 L 必须小于绳子长度 N, 又要大于 1, 所以 1 是断然不能取的;然后,如果 N 是素数的话,答案应该是 0 0 ; 如果 N 恰好等于某个素数 p 的 i 次方(i > 1),那么对于这个素数因子,长度只能取到 pi-1.

#include <cstdio>#include <cstring>#include <cstdlib>#include <map>using namespace std;typedef __int64 ll;ll gcd(ll a,ll b){return (b==0)?a:gcd(b,a%b);}ll Mulmod(ll a,ll b,ll n){    ll  exp = a%n, res = 0;    while(b)    {        if(b&1)        {            res += exp;            if(res>n) res -= n;        }        exp <<= 1;        if(exp>n)            exp -= n;        b>>=1;    }    return res;}ll exp_mod(ll a,ll b,ll c){ll k = 1;while(b){if(b&1)k = Mulmod(k,a,c);a = Mulmod(a,a,c);b>>=1;}return k;}bool Miller_Rabbin(ll n, ll times){    if(n==2)return 1;    if(n<2||!(n&1))return 0;    ll a, u=n-1, x, y;    int t=0;    while(u%2==0){        t++;        u/=2;    }    srand(100);    for(int i=0;i<times;i++)    {        a = rand() % (n-1) + 1;        x = exp_mod(a, u, n);        for(int j=0;j<t;j++)        {            y = Mulmod(x, x, n);            if ( y == 1 && x != 1 && x != n-1 )                return false; //must not            x = y;        }        if( y!=1) return false;    }    return true;}ll Pollard_Rho(ll n,ll c){ll x,y,d,i=1,k=2;y = x = rand() % (n-1) + 1;while(1){i++;x = (Mulmod(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;}}}ll factor[200],cnt;void Find_factor(ll n,ll c){if(n==1)return;if(Miller_Rabbin(n,6)){factor[cnt++] = n;return;}ll p = n;ll k = c;while(p>=n)p = Pollard_Rho(p,c--);Find_factor(p,k);Find_factor(n/p,k);}ll a_b(ll a,ll b){    ll ans = 1;    for(ll i=0; i<b; i++)    ans*=a;    return ans;}int main(){int t;scanf("%d",&t);ll n;while(t--){scanf("%I64d",&n);cnt = 0;Find_factor(n,120);map<ll,int>m0;for(int i=0; i<cnt; i++){    m0[factor[i]]++;}map<ll,int>::iterator iter;int size = m0.size();if(size==1){    printf("%d %I64d\n",size,n/factor[0]);    continue;}ll sum = 0;for(iter=m0.begin(); iter!=m0.end(); iter++)sum+=a_b(iter->first,iter->second);printf("%d %I64d\n",size,sum);}}