poj 2635 千进制

转自:http://www.cnblogs.com/kuangbin/archive/2012/04/01/2429463.html

大致题意:

给定一个大数K,K是两个大素数的乘积的值。

再给定一个int内的数L

问这两个大素数中最小的一个是否小于L,如果小于则输出这个素数。

解题思路:

首先对题目的插图表示无语。。。

高精度求模+同余模定理

1、  Char格式读入K。把K转成千进制Kt,同时变为int型。

把数字往大进制转换能够加快运算效率。若用十进制则耗费很多时间,会TLE。

千进制的性质与十进制相似。

例如,把K=1234567890转成千进制,就变成了:Kt=[  1][234][567][890]。

为了方便处理,我的程序是按“局部有序,全局倒序”模式存放Kt

即Kt=[890][567][234][1  ]  (一个中括号代表一个数组元素)

2、  素数打表,把10^6内的素数全部预打表,在求模时则枚举到小于L为止。

注意打表不能只打到100W,要保证素数表中最大的素数必须大于10^6,否则当L=100W且K为GOOD时,会因为数组越界而RE,这是因为越界后prime都是负无穷的数,枚举的while(prime[pMin]<L)循环会陷入死循环

3、  高精度求模。

主要利用Kt数组和同余模定理。

例如要验证123是否被3整除,只需求模124%3

但当123是一个大数时,就不能直接求,只能通过同余模定理对大数“分块”间接求模

具体做法是:

先求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就可以了

算法思路:千进制表示已知数,进行高精度取余即可,不过大牛们说,百进制TLE,千进制AC,万进制WA,

Sample Input

143 10
143 20
667 20
667 30
2573 30
2573 40
0 0

Sample Output

GOOD
BAD 11
GOOD
BAD 23
GOOD
BAD 31
 1 #include<stdio.h>
 2 #include<string.h>
 3 const int MAXN=1000010;
 4 int prime[MAXN+1];
 5 int getPrime()
 6 {
 7     memset(prime,0,sizeof(prime));
 8     for(int i=2;i<=MAXN;i++)
 9     {
10         if(!prime[i]) prime[++prime[0]]=i;
11         for(int j=1;j<=prime[0]&&prime[j]<=MAXN/i;j++)
12         {
13             prime[prime[j]*i]=1;
14             if(i%prime[j]==0) break;
15         }
16     }
17     return prime[0];
18 }
19
20 int Kt[100];
21 int L;
22 char str[1000];
23
24 bool mod(int *K,int p,int len)
25 {
26     int sq=0;
27     for(int i=len-1;i>=0;i--)
28       sq=(sq*1000+K[i])%p;
29     if(!sq) return false;
30     return true;
31 }
32 int main()
33 {
34     getPrime();
35
36     while(scanf("%s %d",&str,&L)!=EOF)
37     {
38         if(L==0&&strcmp(str,"0")==0) break;
39         int len=strlen(str);
40         memset(Kt,0,sizeof(Kt));
41         for(int i=0;i<len;i++)
42         {
43             int ii=(len+2-i)/3-1;
44             Kt[ii]=Kt[ii]*10+str[i]-‘0‘;
45         }
46         int lenKt=(len+2)/3;
47         bool flag=true;
48         int pMin=1;
49         while(prime[pMin]<L)
50         {
51             if(!mod(Kt,prime[pMin],lenKt))
52             {
53                 flag=false;
54                 printf("BAD %d\n",prime[pMin]);
55                 break;
56             }
57             pMin++;
58         }
59         if(flag) printf("GOOD\n");
60     }
61     return 0;
62 }
时间: 2024-11-13 09:33:53

poj 2635 千进制的相关文章

POJ 1220 高精度/进制转换

n进制转m进制,虽然知道短除法但是还是不太理解,看了代码理解一些了: 记住这个就好了: for(int k=0;l; ){ for(int i=l ; i>=1 ; i--){ num[i - 1] += num[i] % m * n; num [i] / =m; } num[k++]=num[0] % m; num[0] /= m; while( l > 0&& num[ l - 1]==0) l--; } AC代码如下: #include<cstdio> #in

poj 2635 The Embarrassed Cryptographer (同余定理,筛选法)

链接:poj 2635 题意:给定一个大数k,k是两个大素数的乘积的值,再给定一个int内的数L 问这两个大素数中最小的一个是否小于L,如果小于则输出这个素数. 分析:因为k达到了10^100,只能用字符串读入,再转化为千进制,用int数组存储, 然后枚举小于L的素数,看是否能被整除,即判断k%L是否为0, 这样就得先用筛选法求素数打表,但是注意要打表到大于10^6 关于高精度取余,就需要用到同余定理 如 123456%N=(((123%N)*1000%N)+456)%N #include<st

POJ 1220 NUMBER BASE CONVERSION 高精度进制转换

      poj  50题拍照合影留念 NUMBER BASE CONVERSION Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 4620   Accepted: 2115 Description Write a program to convert numbers in one base to numbers in a second base. There are 62 different digits: { 0-

【POJ 1200】Crazy Search(将字符映射为数字,将NC进制hash成10进制)

题目链接 题目链接 http://poj.org/problem?id=1200 题意 原字符串有NC个不同字母,统计原字符串长度为N的子字符串个数 解题思路 将字符按ASCII码映射成数字. 将n个字符,即n位NC进制拼起来. 将拼起来的n位NC进制转化为10进制. 将10进制映射入hash表,每次映射判断是否已经存在. 若不存在,则ans++:否则将hash设置为存在 如何将子串(n位NC进制)映射为10进制 a = 0 b = 1 c = 2 则 cbaa = 2 * 3^3 + 1 *

数学推导+高精度进制转换+解同余方程 POJ 3708

题意:点击打开链接 把m,k表示成d进制,对于这个递归函数,每一次递归都是一次每一位数字的置换,求出每一位的循环节,最终f(m)=k就是要每一位都相等,即解同余方程组. 代码: #include <cstdlib> #include <cctype> #include <cstring> #include <cstdio> #include <cmath> #include<climits> #include <algorith

千峰培训Day02-java基础学习:运算符、进制转换

常用命令:“F:”进入到指定盘符“cd 路径”:进入到指定路径下 javac 编译java执行 标识符:数据类型:基本数据类型.引用数据类型 今日内容: 常量:13变量:一块内容可以改变的内存,存储数据变量名:标识符变量值:内存中的数据变量想被使用,那么必须,先声明后赋值声明的格式:数据类型 变量名;赋值的格式:变量名=变量值;数据类型(声明) 变量名=变量值(赋值);例:int num = 12;格式:数据类型 变量名[=值]; 字符和字符串的区别?字符:单引号,内部只有一个字符字符串:双引号

3255:十进制到六进制-poj

3255:十进制到六进制 总时间限制:  1000ms 内存限制:  65536kB 描述 进制转换: 将十进制(不超过int类型表示的范围)的数转换为六进制的数. 输入 输入为第一行是组数n,后面n行是需要进制转换的十进制数. 输出 进制转换后的n行六进制数. 样例输入 3 13 46 265 样例输出 21 114 1121 来源 cs10107 C++ Final Exam 代码: #include<iostream> using namespace std; int main() {

POj 1170 Shopping Offers(变形背包+进制优化) 100

商店买东西会有优惠政策,使用优惠政策使顾客花的钱尽可能的少. 这道题很有现实背景啊,起初看这道题想的是用规则去优化各种组合情况的物品,并没有想到用背包.因为没有做过"规则"这种物品 还有一点就是接收输入信息的时候若用高维数组很难控制,当时竟然写出了int (*it)[5][5][5][5] 这种东西. 这时,进制优化发挥作用了,其思想类似于康托展开,且因为这个问题并不是直接将位置映射到数集,而是各个不同物品的映射.六进制就够用了.将各个物品映射到一个六进制数字中的每一位,一位上的数字0

NUMBER BASE CONVERSION(进制转换)

Description Write a program to convert numbers in one base to numbers in a second base. There are 62 different digits: { 0-9,A-Z,a-z } HINT: If you make a sequence of base conversions using the output of one conversion as the input to the next, when