POJ1426-Find The Multiple(搜索)
|
Find The Multiple
Description Given a positive integer n, write a program to find out a nonzero multiple m of n whose decimal representation contains only the digits 0 and 1. You may assume that n is not greater than 200 and there is a corresponding m containing no more than 100 decimal digits.
Input The input file may contain multiple test cases. Each line contains a value of n (1 <= n <= 200). A line containing a zero terminates the input.
Output For each value of n in the input print a line containing the corresponding value of m. The decimal representation of m must not contain more than 100 digits. If there are multiple solutions for a given value of n, any one of them is acceptable.
Sample Input 2 Sample Output 10 Source |
||||||||||
题意:给你一个数n,输出一个只有0和1组成的数字,要求它是n的倍数
思路:网上看到一个大佬的写法很牛逼,直接拿来用啦。 http://exp-blog.com/2018/06/22/pid-813/
解题思路:
首先暴力枚举肯定是不可能的 1000ms 想不超时都难,而且枚举还要解决大数问题。。
要不是人家把这题放到搜索,怎么也想不到用BFS。。。
解题方法: BFS+同余模定理
不说废话。
首先说说朴素的不剪枝搜索方法:
我以n=6为例
首先十进制数,开头第一个数字(最高位)一定不能为0,即最高位必为1
设6的 ”01十进制倍数” 为k,那么必有k%6 = 0
现在就是要用BFS求k值
1、先搜索k的最高位,最高位必为1,则此时k=1,但1%6 =1 != 0
因此k=1不是所求,存储余数 1
2、搜索下一位,下一位可能为0,即 k*10+0,此时k=10,那么k%6=4
可能为1,即 k*10+1,此时k=11,那么k%6=5
由于余数均不为0,即k=10与k=11均不是所求
3、继续搜索第三位,此时有四种可能了:
对于k=10,下一位可能为0,即 k*10+0,此时k=100,那么k%6=4
下一位可能为1,即 k*10+1,此时k=101,那么k%6=5
对于k=11,下一位可能为0,即 k*10+0,此时k=110,那么k%6=2
下一位可能为1,即 k*10+1,此时k=111,那么k%6=3
由于余数均不为0,即k=100,k=101,k=110,k=111均不是所求
4、继续搜索第四位,此时有八种可能了:
对于k=100,下一位可能为0,即 k*10+0,此时k=1000,那么k%6=4
下一位可能为1,即 k*10+1,此时k=1001,那么k%6=5
对于k=101,下一位可能为0,即 k*10+0,此时k=1010,那么k%6=2
下一位可能为1,即 k*10+1,此时k=1011,那么k%6=3
对于k=110,下一位可能为0,即 k*10+0,此时k=1100,那么k%6=2
下一位可能为1,即 k*10+1,此时k=1101,那么k%6=3
对于k=111,下一位可能为0,即 k*10+0,此时k=1110,那么k%6=0
下一位可能为1,即 k*10+1,此时k=1111,那么k%6=1
我们发现k=1110时,k%6=0,即1110就是所求的倍数
从上面的演绎不难发现,用BFS是搜索 当前位数字 (除最高位固定为1),因为每一位都只有0或1两种选择,换而言之是一个双入口BFS
本题难点在于搜索之后的处理:对余数的处理,对大数的处理,余数与所求倍数间的关系
接下来说说处理大数问题和剪枝的方法:
首先我们简单回顾一下 朴素搜索 法:
n=6
1%6=1 (k=1)
{
(1*10+0)%6=4 (k=10)
{
(10*10+0)%6=4 (k=100)
{
(100*10+0)%6=4 (k=1000)
(100*10+1)%6=5 (k=1001)
}
(10*10+1)%6=5 (k=101)
{
(101*10+0)%6=2 (k=1010)
(101*10+1)%6=3 (k=1011)
}
}
(1*10+1)%6=5 (k=11)
{
(11*10+0)%6=2 (k=110)
{
(110*10+0)%6=2 (k=1100)
(110*10+1)%6=3 (k=1101)
}
(11*10+1)%6=3 (k=111)
{
(111*10+0)%6=0 (k=1110) 有解
(111*10+1)%6=1 (k=1111) 由于前面有解,这个余数不存储
}
}
}
从上面可以看出余数的存数顺序(逐层存储):
用数组mod[]存储余数,其中mod[0]不使用,由mod[1]开始
那么mod中的余数依次为: 1 4 5 4 5 2 3 4 5 2 3 2 3 0 共14个
即说明我们得到 余数0 之前,做了14步*10的操作,那么当n值足够大的时候,是很容易出现k为大数的情况(事实上我做过统计,200以内的n,有18个n对应的k值为大数
那么我们再用int去存储k就显得不怎么明智了。
为了处理所有情况,我们自然会想到 是不是应该要用int[]去存储k的每一位?
而又由于k是一个01序列,那能不能把 *10得到k每一位的问题 转化为模2的操作得到k的每一位(0或1) 呢?
答案是可以的
首先我们利用 同余模定理 对得到余数的方式进行一个优化
(a*b)%n = (a%n *b%n)%n
(a+b)%n = (a%n +b%n)%n
随便抽取上面一条式子为例
前一步 (11*10+1)%6=2 即k=110 , k%6=2
当前步 (110*10+1)%6=2
由同余模定理 (110*10+1)%6 = ((110*10)%6+1%6 )%6 = ((110%6 * 10%6)%6 +1 )%6
不难发现下划线部分110%6等于 (11*10+0)%6 = 2
所以当前步(110*10+1)%6可以转变为 (2*10+1)%6=2
很显然地,这种处理把k=110 等价于 k=2
即用 前一步操作得到的余数 代替 当前步的k值
而n在200的范围内, 余数值不可能超过3位数, 这就解决了 大数的问题
通过这种处理手法,我们只需在BFS时顺手存储一个 余数数组mod[] ,就能通过mod[i-1]得到mod[i] ,直到mod[i]==0 时结束,大大减少了运算时间
前面已经提到,n=6时,求余操作进行了14次,对应地,BFS时*10的操作也进行了14次。
令i=14,通过观察发现,i%2恰好就是 6 的倍数的最低位数字
i/2 再令 i%2 ,恰好就是 6 的倍数的 次低位数字。。。
循环这个操作,直到i=0,就能得到 6的 01倍数(一个01队列),倒序输出就是所求
这样就完成了 *10操作到 %2操作的过渡
由于n值有限,只是1到200的整数,因此本题也可以用打表做,通过上面的方法得到结果后,就把1~200的倍数打印出来,重新建立一个程序,直接打表就可以了。
不过打表比上面介绍的方法快不了多少
#include<iostream>
using namespace std; int mod[]; //保存每次mod n的余数
//由于198的余数序列是最长的
//经过反复二分验证,436905是能存储198余数序列的最少空间
//但POJ肯定又越界测试了...524286是AC的最低下限,不然铁定RE int main(int i)
{
int n;
while(cin>>n)
{
if(!n)
break; mod[]=%n; //初始化,n倍数的最高位必是1 for(i=;mod[i-]!=;i++) //利用同余模定理,从前一步的余数mod[i/2]得到下一步的余数mod[i]
mod[i]=(mod[i/]*+i%)%n;
//mod[i/2]*10+i%2模拟了BFS的双入口搜索
//当i为偶数时,+0,即取当前位数字为0 。为奇数时,则+1,即取当前位数字为1 i--;
int pm=;
while(i)
{
mod[pm++]=i%; //把*10操作转化为%2操作,逆向求倍数的每一位数字
i/=;
}
while(pm)
cout<<mod[--pm]; //倒序输出
cout<<endl;
}
return ;
}
POJ1426-Find The Multiple(搜索)的更多相关文章
- POJ1426——Find The Multiple
POJ1426--Find The Multiple Description Given a positive integer n, write a program to find out a non ...
- POJ1426——Find The Multiple (简单搜索+取余)
题意: 给一个数n,让你找出一个只有1,0,组成的十进制数,要求是找到的数可以被n整除. 用DFS是搜索 当前位数字 (除最高位固定为1),因为每一位都只有0或1两种选择,换而言之是一个双入口BFS. ...
- poj1426 Find The Multiple(c语言巧解)
Find The Multiple Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 36335 Accepted: 151 ...
- poj 1426 Find The Multiple 搜索进阶-暑假集训
E - Find The Multiple Time Limit:1000MS Memory Limit:10000KB 64bit IO Format:%I64d & %I6 ...
- POJ1426 Find The Multiple —— BFS
题目链接:http://poj.org/problem?id=1426 Find The Multiple Time Limit: 1000MS Memory Limit: 10000K Tota ...
- POJ1426 Find The Multiple (宽搜思想)
Find The Multiple Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 24768 Accepted: 102 ...
- HDU 4294 Multiple(搜索+数学)
题意: 给定一个n,让求一个M,它是n个倍数并且在k进制之下 M的不同的数字最少. 思路: 这里用到一个结论就是任意两个数可以组成任何数的倍数.知道这个之后就可以用搜索来做了.还有一个问题就是最多找n ...
- poj1426 Find The Multiple
Find The Multiple Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 14622 Accepted: 593 ...
- POJ1426:Find The Multiple(算是bfs水题吧,投机取巧过的)
http://poj.org/problem?id=1426 Description Given a positive integer n, write a program to find out a ...
- poj1426 Find The Multiple (DFS)
题目: Find The Multiple Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 41845 Accepted: ...
随机推荐
- Oracle之rman数据库在非归档模式下的备份和恢复
1.数据库在非归档模式下的备份 SQL> archive log list;数据库日志模式 非存档模式自动存档 禁用存档终点 USE_DB_RECOVERY_FILE_DEST最早的联机日志序列 ...
- 如何远程连接非默认端口SQL Server
SQL Server Management Studio建立远程SQL连接 连接的时候写: 127.0.0.1,49685\sqlexpress 记得使用逗号,不是冒号
- java如何导入Excel文件
Java使用POI导入Excel文件,操作起来比较简单,支持xlsx格式. 下载POI资源包 从官网https://poi.apache.org/下载POI,笔者选择的是版本是3.17,下载后文件名是 ...
- JS中关于clientWidth offsetWidth scrollWidth 等的区别
网页可见区域宽: document.body.clientWidth;网页可见区域高: document.body.clientHeight;网页可见区域宽: document.body.offset ...
- 十分钟玩转 jQuery、实例大全(参考自博主索宁)
十分钟玩转 jQuery.实例大全(参考自博主索宁) 一.简介 书写规则 支持链式操作: 在变量前加"$"符号(var $variable = jQuery 对象): 注:此规定并 ...
- happy2018暑期集训课后习题001
根据需求补全下面的代码: 需求: 每行输入三个整数a.b.c,根据a的值不同对b和c进行不同的操作: a为0时,计算b+c a为1时,计算b-c a为2时,计算b*c a为3时,计算b/c 并输出操作 ...
- .net reflector 的缺陷
.net reflector是一个反编译DLL的工具,在安装后如果电脑上有VS也会同时安装到VS里面,但是他是收费的,虽然反编译的效果很好,但是运行VS2013时(或许其他版本也有这样的问题)如果项目 ...
- POJ 3057 Evacuation(二分匹配)
分析: 这是一个时间和门的二元组(t,d)和人p匹配的问题,当我们固定d0时,(t,d0)匹配的人数和t具有单调性. t增加看成是多增加了边就行了,所以bfs处理出p到每个d的最短时间,然后把(t,d ...
- bzoj2600 [Ioi2011]ricehub
Description 乡间有一条笔直而长的路称为“米道”.沿着这条米道上 R 块稻田,每块稻田的坐标均为一个 1 到 L 之间(含 1 和 L)的整数.这些稻田按照坐标以不减的顺序给出,即对于 0 ...
- 【BZOJ1972】[SDOI2010] 猪国杀(恶心的大模拟)
点此看题面 大致题意: 让你模拟一个游戏猪国杀的过程. 几大坑点 对于这种模拟题,具体思路就不讲了,就说说有哪些坑点. 题面有锅,反猪是\(FP\). 数据有锅,牌堆中的牌可能不够用,牌堆为空之后需一 ...