poj2635 同余定理 + 素数筛法
2017-02-14 13:20
267 查看
题意:给定一个数,这个数是两个素数的乘积,并给定一个限制L,问是否两个素数中存在小于L的数,若存在输出较小质数,否则打印‘GOOD’。
思路:
1 . x = a * b, a和b都是素数,那么x只能分解为(1,x)或则(a,b),因为 x 只有四个因子1,a,b,x。
2 . 判定某大数y能否被x整除,可以通过求余是否为0判断。大数求余的方法在我的上一篇文章中有证明。
3 . 素数打表,方便快速判断某个数是否为质数。
根据第一个结论,可以知道如果某个素数(这个数小于限制L)能被大数整除,那么这个数就是最小质数,就可以结束判断。
AC代码
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
const int maxn = 1000005;
int vis[maxn], prim[maxn], a[105];
char s[105];
int deal(int n){
int m = sqrt(n + 0.5);
memset(vis, 0, sizeof(vis));
for(int i = 2; i <= m; ++i) if(!vis[i])
for(int j = i*i; j <= n; j += i) vis[j] = 1;
int cnt = 0;
for(int i = 2; i < n; ++i){
if(!vis[i]) prim[cnt++] = i;
}
return cnt;
}
// 转换千进制
int turn(int n){
memset(a, 0, sizeof(a));
int c = 0;
int m = n % 3;
for(int i = 0; i < m; ++i) a[c] = a[c] * 10 + s[i] - '0';
if(m) ++c;
for(int i = m; i < n; i += 3){
for(int j = i; j < i + 3; ++j)
a[c] = a[c] * 10 + s[j] - '0';
++c;
}
return c;
}
bool mod(int x, int n) {
int m = 0;
for(int i = 0; i < n; ++i){
m = (m * 1000+ a[i]) % x;
}
if(m == 0) return true;
return false;
}
int main(){
int n = deal(maxn);
int h;
while(scanf("%s%d", s, &h) == 2 && h){
int len = strlen(s);
len = turn(len);
int flag = 1;
for(int i = 0; prim[i] < h && i < n; ++i) {
if(mod(prim[i], len)) {
printf("BAD %d\n", prim[i]);
flag = 0;
break;
}
}
if(flag) printf("GOOD\n");
}
return 0;
}
如有不当之处欢迎指出!
思路:
1 . x = a * b, a和b都是素数,那么x只能分解为(1,x)或则(a,b),因为 x 只有四个因子1,a,b,x。
2 . 判定某大数y能否被x整除,可以通过求余是否为0判断。大数求余的方法在我的上一篇文章中有证明。
3 . 素数打表,方便快速判断某个数是否为质数。
根据第一个结论,可以知道如果某个素数(这个数小于限制L)能被大数整除,那么这个数就是最小质数,就可以结束判断。
AC代码
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
const int maxn = 1000005;
int vis[maxn], prim[maxn], a[105];
char s[105];
int deal(int n){
int m = sqrt(n + 0.5);
memset(vis, 0, sizeof(vis));
for(int i = 2; i <= m; ++i) if(!vis[i])
for(int j = i*i; j <= n; j += i) vis[j] = 1;
int cnt = 0;
for(int i = 2; i < n; ++i){
if(!vis[i]) prim[cnt++] = i;
}
return cnt;
}
// 转换千进制
int turn(int n){
memset(a, 0, sizeof(a));
int c = 0;
int m = n % 3;
for(int i = 0; i < m; ++i) a[c] = a[c] * 10 + s[i] - '0';
if(m) ++c;
for(int i = m; i < n; i += 3){
for(int j = i; j < i + 3; ++j)
a[c] = a[c] * 10 + s[j] - '0';
++c;
}
return c;
}
bool mod(int x, int n) {
int m = 0;
for(int i = 0; i < n; ++i){
m = (m * 1000+ a[i]) % x;
}
if(m == 0) return true;
return false;
}
int main(){
int n = deal(maxn);
int h;
while(scanf("%s%d", s, &h) == 2 && h){
int len = strlen(s);
len = turn(len);
int flag = 1;
for(int i = 0; prim[i] < h && i < n; ++i) {
if(mod(prim[i], len)) {
printf("BAD %d\n", prim[i]);
flag = 0;
break;
}
}
if(flag) printf("GOOD\n");
}
return 0;
}
如有不当之处欢迎指出!
相关文章推荐
- 森德拉姆素数筛法
- ZOJ 1314题解此题一开始用的方法不对,最后经别人提醒改用同余定理果然AC了
- POJ 2689 素数筛法
- 素数筛法和测试
- poj2769 Reduced ID Numbers 同余定理
- 素数筛法程序实现
- poj2635
- 素数筛法模板
- 数论专题小结:素数筛法
- AOJ - 0009 Prime Number (素数筛法) && AOJ - 0005 (求最大公约数和最小公倍数)
- HDOJ 2674 N!Again(同余定理)
- POJ 1995 Raising Modulo Numbers 【快速幂&&同余定理】
- LightOJ 1078 - Integer Divisibility (同余定理)
- 素数判断和素数筛法
- 求素数:普通版素数筛法/快速版素数筛法
- [数论]poj2635__The Embarrassed Cryptographer
- poj2635
- POJ 1426 (BFS + 同余定理)
- LightOJ1278 Sum of Consecutive Integers 素数筛法+数学分析
- Lonlife-ACM 1005 - Spoon Devil's RP Test(同余定理)——“玲珑杯”acm比赛-试运行赛