Miller-Rabin
大素数测试
Miller-Rabin算法本质上是一种概率算法,存在误判的可能性,但是出错的概率非常小。出错的概率到底是多少,存在严格的理论推导。
费马小定理
若 (p) 是素数, (gcd(a,p) = 1) , 那么 (a^{p-1} = 1 (mod p))
如果存在 $a < p $ , 且 (a^{p-1} \% p e 1) , 则 (p) 肯定不是素数
有限域上的平方根定理
如果 (p) 是一个奇素数且 (e ge 1) ,则
[x^2 = 1 (mod p^e) ]仅有两个根 (x = 1) 或 (x = -1) , 注意到在模 (p) 的意义下 (x = -1) 等价于 (x = p - 1) , 正负一 也被称为 (1) 的平凡平方根
如果对模 (n) 存在 (1) 的非平凡平方根, (n) 一定是合数
...
没有很懂
抄了个板子,A 了 19徐州那道题
但是只过了洛谷的板子的两个点
还顺带把 CCPC威海的 D 题给 AC了
(判断有没有一个质因数的次数大于等于2)
signed main(){
scanf("%lld",&T);
while(T--){
ans = 0;
scanf("%lld",&n);m.clear();
find(n);
if(ans)puts("yes");
else puts("no");
}
}
这个板子用着应该是没啥问题
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 1e5 + 5;
int x[105];
int mul(int a, int b, int p){
int ans = 0;
while (b){
if (b & 1LL) ans = (ans + a) % p;
a = (a + a) % p;
b >>= 1;
}
return ans;
}
int qpow(int a, int b, int p){
int ans = 1;
while (b){
if (b & 1LL) ans = mul(ans, a, p);
a = mul(a, a, p);
b >>= 1;
}
return ans;
}
bool Miller_Rabin(int n){ //大素数测试
if (n == 2) return true;
int s = 20, i, t = 0;
int u = n - 1;
while (!(u & 1))
{
t++;
u >>= 1;
}
while (s--)
{
int a = rand() % (n - 2) + 2;
x[0] = qpow(a, u, n);
for (i = 1; i <= t; i++)
{
x[i] = mul(x[i - 1], x[i - 1], n);
if (x[i] == 1 && x[i - 1] != 1 && x[i - 1] != n - 1)
return false;
}
if (x[t] != 1) return false;
}
return true;
}
int gcd(int a, int b){
return b ? gcd(b, a % b) : a;
}
int Pollard_Rho(int n, int c){
int i = 1, k = 2, x = rand() % (n - 1) + 1, y = x;
while (1){
i++;
x = (mul(x, x, n) + c) % n;
int p = gcd((y - x + n) % n, n);
if (p != 1 && p != n) return p;
if (y == x) return n;
if (i == k){
y = x;
k <<= 1;
}
}
}
map<int, int> m;
void find(int n, int c = 12345)
{
if (n == 1) return;
if (Miller_Rabin(n)){
m[n]++;
return;
}
int p = n, k = c;
while (p >= n) p = Pollard_Rho(p, c--);
find(p, k);
find(n / p, k);
}
E - Multiply
直接上板子
int T, n, X, Y, A[100010];
int cal(int n, int p) {
int ans = 0;
while (n) {
ans += n / p;
n /= p;
}
return ans;
}
map<int, int>mp;
signed main() {
scanf("%lld", &T);
while (T--) {
scanf("%lld%lld%lld", &n, &X, &Y);
for (int i = 1; i <= n; i++)scanf("%lld", A + i);
m.clear(); mp.clear();
find(X);
for (auto& i : m) {
mp[i.first] += cal(Y, i.first);
}
for (auto& i : m) {
for (int j = 1; j <= n; j++) {
mp[i.first] -= cal(A[j], i.first);
}
}
int ans = 1e18;
for (auto& i : m) {
ans = min(ans, mp[i.first] / i.second);
}
printf("%lld
", ans);
}
}