依据惯例,贴上题目链接http://poj.org/problem?id=2635
这道题的大意是给你一个大数k,一个普通数字l,并且该大数可表示成两个质数的乘积,如果较小的那个质数小于l,则输出这个质数, 0 0时结束。
这道题目我开始想采用大数分解来做,但是这样子做未免过于麻烦,根据题意,我们可以遍历2 —>l,如果我们找到了一个数n,
使得k % n = 0 成立,我们直接输出即可,若没有找到,就'GOOD'啦~
因此,此题的难点在于素数筛(这个直接靠模板吧,可以将打表的过程省略,只需要记录该数字是否为质数即可) 和 大数取模。
大数取模: 这里用一下某大佬的博客中的例子:
以10进制数124%3为例
具体做法是:
先求1%3 = 1
再求(1*10+2)%3 = 0
再求 (0*10+4)% 3 = 1
那么就间接得到124%3=1,这是显然正确的
而且不难发现, (1*10+2)*10+4 = 124
这是在10进制下的做法,千进制也同理,*10改为*1000就可以了
那么我们如何将10进制转化为千进制呢,我们这里不一定非要转换之后再做,我们不妨将大数k以3位为一组切开,分开取模再相加。
AC代码如下:
#include<cstdio>
#include<iostream>
#include<cstring>
#include<cmath>
using namespace std;
const int maxn = 1000005;
int vis[maxn], prime[maxn], k[105];
char str[110];
int m, l;
int max(int x, int y)
{
if(x > y)
return x;
else
return y;
}
void primes()
{
int ans = sqrt(maxn) + 0.5;
memset(vis, 0, sizeof(vis));
for(int i = 2; i <= ans; i++){
if(!vis[i])
for(int j = i*i; j < maxn; j+=i)
vis[j] = 1;
}
}
void trans(char str[])
{
int len = strlen(str);
m = 0;
for(int i = len-1; i >= 0; i -= 3){
k[m] = 0;
for(int j = max(i-2, 0); j <= i; j++){
k[m] = k[m]*10 + (str[j]-'0');
}
m++;
}
}
int mod(int x)
{
int r = 0;
for(int i = m-1; i >= 0; i--){
r = (r*1000+k[i]) % x;
}
return r;
}
int main()
{
primes();
while(cin >> str >> l){
if(str[0] == '0' && l == 0)
break;
trans(str);
int i;
for(i = 2; i < l; i++){
if(!vis[i] && !mod(i)){
cout << "BAD " << i << endl;
break;
}
}
if(i >= l)
cout << "GOOD" << endl;
}
return 0;
}