题目大意
要求给定一个数(而且这个数能被分解成两个质数的乘积)的小的那个因子。如果该因子严格小于给定的数字L,那么就说明这个密码很弱(BAD),否则就说这个密码是好的(GOOD)
思路概要 & 算法分析
先用线性筛搞出 1 e 6 1e6 1e6内所有的质数,根据 n ln n \frac{n}{\ln n} lnnn估算素数大约有 75000 75000 75000个,然后进行大数取模,使用秦九昭算法时间复杂度O(位数),因为位数最大为100,所以判断一个数 X X X是否有 Y Y Y内的质因数的时间复杂度就是 O ( lg x ∗ y ln y ) O(\lg x * \frac{y}{\ln y}) O(lgx∗lnyy) = O ( y ∗ log x ) O(y * \log x) O(y∗logx),在本题中就是 7 e 6 7e6 7e6,然后最多20组样例,大约 1 e 8 1e8 1e8的时间(极限数据)。
注意点
看清楚题目,给定的数字只能被分解成一组质数相乘,开始看错了…一直在想如何进行判定大素数,线性筛都要
O
(
n
)
O(n)
O(n),然后随机探测法判断单个要
O
(
n
1
4
)
O(n^{\frac{1}{4}})
O(n41),然后看了看题目发现只要找到第一个合法的就行。
这么看来就好水啊干
#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdlib>
#include <stack>
#include <cmath>
#include <string.h>
#include <string>
#include <map>
#include <vector>
using namespace std;
typedef long long ll;
char s[999];
int m;
const int N = 1e6 + 10;
ll p[N], st[N], cnt;
int big_mod(int k) {
int q = 0;
for (int i = 0; s[i]; i++) {
q = (q * 10 + s[i] - '0') % k;
}
return q;
}
int check() {
int c = 0;
for (int i = 1; i <= cnt && p[i] < m; i++) {
// cout << i << " " << mod(s, i) << endl;
if (big_mod(p[i]) == 0) {
return p[i];
}
}
return 0;
}
void init(int n) {
for (int i = 2; i <= n; i++) {
if (!st[i]) p[++cnt] = i;
for (int j = 1; i * p[j] <= n; j++) {
st[i * p[j]] = 1;
if (i % p[j] == 0) break;
}
}
}
int main() {
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
#endif // !ONLINE_JUDGE
init(1e6);
while (scanf("%s%d", s, &m)) {
if (m == 0) break;
int t;
t = check();
if (t == 0) {
printf("GOOD\n");
}
else {
printf("BAD %d\n", t);
}
}
return 0;
}