HDU 4344 Mark the Rope

来源:互联网 发布:海底捞排号软件 编辑:程序博客网 时间:2024/06/06 23:54

Millar-Rabin +Pollard Rho

我的MR在输入2的时候会挂,因为模0了;

我的PR在输入4的时候会挂,因为出现一点偏差详见代码注释……

关于Pollard Rho推荐:https://wenku.baidu.com/view/3db5c7a6ad51f01dc381f156.html

我也不知道为什么那样子做复杂度是对的…..

实测,像什么x = x * 2333 + c的函数都不如文章里说的x = x * x + c来得快,感觉挺玄学……没找到什么文献,如果有相关的东西求告知……

#include<cstdio>#include<algorithm>using namespace std;namespace runzhe2000{    typedef unsigned long long ll;    ll n, cur; const ll A = 20000107, B = 3333331;     ll randll(){return cur = cur * A + B;}    ll fmul(ll a, ll b, ll p)    {        ll r = 0;        for(; b; b >>= 1)        {            if(b&1)(r+=a)%=p;            (a+=a)%=p;        }        return r;    }    ll fpow(ll a, ll b, ll p)    {        ll r = 1;        for(; b; b >>= 1)        {            if(b&1)r=fmul(r,a,p);            a=fmul(a,a,p);        }        return r;    }    int MR(ll n)    {        if(n == 2) return true;        ll a = n-1, b = 0;        for(; !(a&1); a>>=1, b++);        for(int t = 10; t; t--)        {            ll x = randll()%(n-2)+2, pre;            x = pre = fpow(x, a, n);            for(int i = 0; i < (int)b; i++)            {                x = fmul(x,x,n);                if(x==1&&pre!=1&&pre!=n-1)return false;                pre = x;            }            if(x != 1) return false;        }        return true;    }    ll gcd(ll a, ll b){return b?gcd(b,a%b):a;}    ll PR(ll n, int c)    {        if(n == 4) return 2; //在模4意义下,两次循环以后就相等了,我也不知道为什么这么巧         ll x = 2, y = 2, p = 1;        for(; p == 1; )        {            x = fmul(x,x,n)+c;            y = fmul(y,y,n)+c;            y = fmul(y,y,n)+c;            if(x == y) return n;            p = gcd(n, (y-x+n)%n);        }        return p;    }    ll ans, q[2333333]; int tail;    void find(ll x, int c)    {        if(x == 1) return;        if(MR(x))q[tail++] = x;        else        {            ll p = x;            for(; p==x; ) p = PR(x,c++);            find(x/p, c); find(p, c);        }    }    void main()    {        int T; scanf("%d",&T);        for(; T--; )        {            scanf("%lld",&n);            tail = ans = 0; find(n,1);            sort(q, q+tail); int cnt = 0;            ll tmp = 0;            for(int i = 0; i < tail; i++)            {                if(q[i] != q[i-1])                {                    ans += tmp;                    ++cnt;                    tmp = 1;                }                tmp *= q[i];            }            ans += tmp;            if(cnt == 1) ans /= q[0];            printf("%d %lld\n",cnt, ans);        }    }}int main(){    runzhe2000::main();}
0 0
原创粉丝点击