您的位置:首页 > 其它

poj 1811 + poj 2429 (Miller_Rabin大素数测试 + Pollard_Rho大合数分解)

2015-01-05 20:42 363 查看
poj 1811:

题意:

判断一个数是否是素数,若不是输出其最小因子。

代码:

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <stack>
#include <vector>
#include <queue>
#include <map>
#include <climits>
#include <cassert>
#define LL long long

using namespace std;

const LL inf = 1LL << 61;
const int Times = 11;
const int Random = 2333;
///
LL bb[200 + 10];
int cnt = 0;
///
LL mini;

LL gcd(LL a, LL b)
{
return b ? gcd(b, a % b) : a;
}

LL Mult_Mod(LL a, LL b, LL mod)// a * b % mod
{
LL res = 0;
while (b)
{
if (b & 1)
res = (res + a) % mod;
b >>= 1;
a = (a << 1) % mod;
}
return res;
}

LL Pow_Mod(LL a, LL b, LL mod)
{
if (b == 0)
return 1;
LL x = Pow_Mod(a, b >> 1, mod);
LL res = Mult_Mod(x, x, mod);
if (b % 2)
res = Mult_Mod(a, res, mod);
return res;
}

bool Witness(LL a, LL n)
{
LL t = 0, m = n - 1;
while (!(m & 1))
{
t++;
m >>= 1;
}
LL x = Pow_Mod(a, m, n);
if (x == 1 || x == n - 1)
return false;
while (t--)
{
x = x * x % n;
if (x == n - 1)
return false;
}
return true;
}

bool Miller_Rabin(LL n)
{
if (n < 2)
return false;
if (n == 2)
return true;
if (!(n & 1))
return false;
for (int i = 1; i <= Times; i++)
{
LL a = rand() % (n - 1) + 1;
if (Witness(a, n))
return false;
}
return true;
}

LL Pollard_Rho(LL n, LL c)
{
LL x = rand() % n;
LL y = x;
LL i = 1, k = 2;
LL d;
while (1)
{
i++;
x = (Mult_Mod(x, x, n) + c) % n;
d = gcd(y - x, n);
if (1 < d && d < n)
return d;
if (y == x)
return n;
if (i == k)
{
y = x;
k <<= 1;
}
}
}

void Get_Small(LL n, LL k)
{
if (n == 1)
return;
if (Miller_Rabin(n))
{
///
bb[++cnt] = n;
///
mini = min(mini, n);
return;
}
LL p = n;
while (n <= p)
p = Pollard_Rho(p, k--);
Get_Small(p, k);
Get_Small(n / p, k);
}

int main()
{
#ifdef LOCAL
freopen("in.txt", "r", stdin);
#endif // LOCAL
int ncase;
scanf("%d", &ncase);
while (ncase--)
{
LL n;
scanf("%lld", &n);
mini = inf;
if (Miller_Rabin(n))
{
printf("Prime\n");
}
else
{
Get_Small(n, Random);
printf("%lld\n", mini);
}
}
return 0;
}


poj 2429:

题意:

给[ a, b ] 和 ( a, b ),求a,b。

解析:

( a * b ) / gcd = lcm.

( a / gcd * b / gcd ) * gcd = lcm.

( a / gcd * b / gcd ) = lcm / gcd.

题目转化为 lcm / gcd 分解成两个互质的数使这两个数的和最小。

将 lcm / gcd 整数分解,深搜搭配因子。

代码:

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <stack>
#include <vector>
#include <queue>
#include <map>
#include <climits>
#include <cassert>
#define LL long long

using namespace std;

const LL inf = 1LL << 61;
const int Times = 11;
const int Random = 2333;
///
LL bb[200 + 10];
int cnt;
///
unsigned long long mini;

LL gcd(LL a, LL b)
{
return b ? gcd(b, a % b) : a;
}

LL Mult_Mod(LL a, LL b, LL mod)// a * b % mod
{
LL res = 0;
while (b)
{
if (b & 1)
res = (res + a) % mod;
b >>= 1;
a = (a << 1) % mod;
}
return res;
}

LL Pow_Mod(LL a, LL b, LL mod)
{
if (b == 0)
return 1;
LL x = Pow_Mod(a, b >> 1, mod);
LL res = Mult_Mod(x, x, mod);
if (b % 2)
res = Mult_Mod(a, res, mod);
return res;
}

bool Witness(LL a, LL n)
{
LL t = 0, m = n - 1;
while (!(m & 1))
{
t++;
m >>= 1;
}
LL x = Pow_Mod(a, m, n);
if (x == 1 || x == n - 1)
return false;
while (t--)
{
x = x * x % n;
if (x == n - 1)
return false;
}
return true;
}

bool Miller_Rabin(LL n)
{
if (n < 2)
return false;
if (n == 2)
return true;
if (!(n & 1))
return false;
for (int i = 1; i <= Times; i++)
{
LL a = rand() % (n - 1) + 1;
if (Witness(a, n))
return false;
}
return true;
}

LL Pollard_Rho(LL n, LL c)
{
LL x = rand() % n;
LL y = x;
LL i = 1, k = 2;
LL d;
while (1)
{
i++;
x = (Mult_Mod(x, x, n) + c) % n;
d = gcd(y - x, n);
if (1 < d && d < n)
return d;
if (y == x)
return n;
if (i == k)
{
y = x;
k <<= 1;
}
}
}

void Get_Small(LL n, LL k)
{
if (n == 1)
return;
if (Miller_Rabin(n))
{
///
bb[++cnt] = n;
///
return;
}
LL p = n;
while (n <= p)
p = Pollard_Rho(p, k--);
Get_Small(p, k);
Get_Small(n / p, k);
}

unsigned long long key, gd, lm,res_a, res_b;
unsigned long long numFactor[650];
LL num[65], Len;

void Dfs(int cur, LL value)
{
LL s = 1;
if (cur == Len + 1)
{
LL a = value;
LL b = key / value;
if (gcd(a, b) == 1)
{
a *= gd;
b *= gd;
if (a + b < mini)
{
mini = a +  b;
res_a = a < b ? a : b;
res_b = a > b ? a : b;
}
}
return;
}
for (int i = 0; i <= num[cur]; i++)
{
if (mini <= value * s)
return;
Dfs(cur + 1, value * s);
s *= numFactor[cur];
}
}

void solve(LL n)
{
cnt = 0;
Get_Small(n, Random);
sort(bb + 1, bb + cnt + 1);
Len = 0;
memset(num, 0, sizeof(num));
num[0] = 1;
numFactor[0] = bb[1];
for (int i = 2; i <= cnt; i++)
{
if (numFactor[Len] != bb[i])
{
numFactor[++Len] = bb[i];
}
num[Len]++;
}
Dfs(0, 1);
}

int main()
{
#ifdef LOCAL
freopen("in.txt", "r", stdin);
#endif // LOCAL
while (scanf("%lld%lld", &gd, &lm) == 2)
{
if (gd == lm)
{
printf("%lld %lld\n", gd, lm);
}
else
{
mini = -1;
key = lm / gd;
solve(key);
printf("%lld %lld\n", res_a, res_b);
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: