POJ--2635The Embarrassed Cryptographer(大数取模)

依据惯例,贴上题目链接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;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值