下面是我的 75pts 代码,四个点超时。
#include <bits/stdc++.h>
#define ull unsigned long long
#define ll long long
#define ld long double
using namespace std;
int t;
ll ksc (ll x, ll y, ll p)
{
return ((ull) x * y - (ull) ((ld) x / p * y) * p + p) % p;
}
ll gcd (ll a, ll b)
{
if (a < b) swap (a, b);
if (b == 0) return a;
else return gcd (b, a % b);
}
ll ksm (ll a, ll b, ll mod)
{
if (b == 0) return 1;
if (b == 1) return a % mod;
ll mid = ksm (a, b / 2, mod);
mid = ksc (mid, mid, mod);
if (b % 2 == 0) return mid;
else return ksc (mid, a, mod);
}
ll test[11] = {0, 2, 3, 5, 7, 11, 13, 17, 19, 23, 29};
bool Miller_Robin (ll n)
{
if (n < 2) return false;
for (int i = 1; i <= 10; i++)
{
ll a = test[i];
if (n == a) return true;
if (ksm (a, n - 1, n) != 1) return false;
ll t = n - 1;
while (! (t & 1) && t != 0)
{
t >>= 1;
ll cur = ksm (a, t, n);
if (cur != n - 1 && cur != 1) return false;
if (cur == n - 1) break;
}
}
return true;
}
ll Pollard_Rho (ll n)
{
if (n == 4) return 2;
srand (time (0));
ll a = rand () % (n - 1) + 1,
c = rand () % (n - 3) + 3;
ll b = a;
a = (ksc (a, a, n) + c) % n;
b = (ksc (b, b, n) + c) % n,
b = (ksc (b, b, n) + c) % n;
for (int lim = 1; a != b; lim = min (lim << 1, 128))
{
ll cnt = 1;
for (int stp = 1; stp <= lim; stp++)
{
ll tmp = ksc (cnt, abs (b - a), n);
if (!tmp) break;
cnt = tmp;
a = (ksc (a, a, n) + c) % n;
b = (ksc (b, b, n) + c) % n,
b = (ksc (b, b, n) + c) % n;
}
ll d = gcd (cnt, n);
if (d != 1) return d;
}
return n;
}
ll ans = 0;
void Get_Maxfactor (ll n)
{
ll d = Pollard_Rho (n), di;
while (d == n) d = Pollard_Rho (n);
di = n / d;
if (Miller_Robin (d)) ans = max (ans, d);
else Get_Maxfactor (d);
if (Miller_Robin (di)) ans = max (ans, di);
else Get_Maxfactor (di);
return;
}
int main ()
{
scanf ("%d", &t);
while (t--)
{
ll x;
scanf ("%lld", &x);
if (Miller_Robin (x))
printf ("Prime\n");
else
{
ans = 0;
Get_Maxfactor (x);
printf ("%lld\n", ans);
}
}
return 0;
}
下面是我的 AC 代码,与上代码的区别是删除了 srand(time(0)) 这个语句。
#include <bits/stdc++.h>
#define ull unsigned long long
#define ll long long
#define ld long double
using namespace std;
int t;
ll ksc (ll x, ll y, ll p)
{
return ((ull) x * y - (ull) ((ld) x / p * y) * p + p) % p;
}
ll gcd (ll a, ll b)
{
if (a < b) swap (a, b);
if (b == 0) return a;
else return gcd (b, a % b);
}
ll ksm (ll a, ll b, ll mod)
{
if (b == 0) return 1;
if (b == 1) return a % mod;
ll mid = ksm (a, b / 2, mod);
mid = ksc (mid, mid, mod);
if (b % 2 == 0) return mid;
else return ksc (mid, a, mod);
}
ll test[11] = {0, 2, 3, 5, 7, 11, 13, 17, 19, 23, 29};
bool Miller_Robin (ll n)
{
if (n < 2) return false;
for (int i = 1; i <= 10; i++)
{
ll a = test[i];
if (n == a) return true;
if (ksm (a, n - 1, n) != 1) return false;
ll t = n - 1;
while (! (t & 1) && t != 0)
{
t >>= 1;
ll cur = ksm (a, t, n);
if (cur != n - 1 && cur != 1) return false;
if (cur == n - 1) break;
}
}
return true;
}
ll Pollard_Rho (ll n)
{
if (n == 4) return 2;
ll a = rand () % (n - 1) + 1,
c = rand () % (n - 3) + 3;
ll b = a;
a = (ksc (a, a, n) + c) % n;
b = (ksc (b, b, n) + c) % n,
b = (ksc (b, b, n) + c) % n;
for (int lim = 1; a != b; lim = min (lim << 1, 128))
{
ll cnt = 1;
for (int stp = 1; stp <= lim; stp++)
{
ll tmp = ksc (cnt, abs (b - a), n);
if (!tmp) break;
cnt = tmp;
a = (ksc (a, a, n) + c) % n;
b = (ksc (b, b, n) + c) % n,
b = (ksc (b, b, n) + c) % n;
}
ll d = gcd (cnt, n);
if (d != 1) return d;
}
return n;
}
ll ans = 0;
void Get_Maxfactor (ll n)
{
ll d = Pollard_Rho (n), di;
while (d == n) d = Pollard_Rho (n);
di = n / d;
if (Miller_Robin (d)) ans = max (ans, d);
else Get_Maxfactor (d);
if (Miller_Robin (di)) ans = max (ans, di);
else Get_Maxfactor (di);
return;
}
int main ()
{
scanf ("%d", &t);
while (t--)
{
ll x;
scanf ("%lld", &x);
if (Miller_Robin (x))
printf ("Prime\n");
else
{
ans = 0;
Get_Maxfactor (x);
printf ("%lld\n", ans);
}
}
return 0;
}
为什么随机化种子就出问题了/kk