Find The Multiple
Time Limit: 1000MS   Memory Limit: 10000K
Total Submissions: 25721   Accepted: 10608   Special Judge

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
6
19
0

Sample Output

10
100100100100100100
111111111111111111

Source

题意:

给一个数n,让你找出一个只有1,0,组成的十进制数,要求是找到的数可以被n整除。

做法:

假如n=6;

1余n=1;

10余n=1*10%6=4;

11余n=(1*10+1)%6=5;

100余n=4*10%6=4;

101余n=(4*10+1)%6=5;

110余n=5*10%6=2;

111余n=(5*10+1)%6=3;

可以推知10。。。。01余n=(10。。。。0余n*10+1)余n

 

解题思路:

首先暴力枚举肯定是不可能的 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<cstdio>
#include<iostream>
using namespace std;
#define N 550000
int n,mod[N];
int main(){
while(scanf("%d",&n)&&n){
int i;mod[i=]=%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 p=;
while(i)
mod[p++]=i%,i>>=;//把*10操作转化为%2操作,逆向求倍数的每一位数字
while(p)
cout<<mod[--p];//倒序输出
cout<<endl;
}
return ;
}

xzc's code:

#include<queue>
#include<cstdio>
#include<iostream>
#include<algorithm> using namespace std; int n; void bfs(int k)
{
queue<long long>que;
que.push();
while (!que.empty())
{
long long now=que.front();
if (now%n!=)
{
que.push(now*);
que.push(now*+);
}
else {cout<<now<<endl;return;}
que.pop();
}
} int main()
{
while (scanf("%d",&n)==&&n)
{
bfs(n);
}
return ;
}

Poj1426的更多相关文章

  1. 广搜 poj3278 poj1426 poj3126

    Catch That Cow Time Limit: 2000 MS Memory Limit: 65536 KB 64-bit integer IO format: %I64d , %I64u Ja ...

  2. poj1426(暴力dfs)

    题目链接:https://vjudge.net/problem/POJ-1426 题意:给出n(1<=n<=200),求出全部由01组成的能整除n的正整数. 思路:此题在unsigned ...

  3. POJ1426——Find The Multiple

    POJ1426--Find The Multiple Description Given a positive integer n, write a program to find out a non ...

  4. POJ1426 Find The Multiple (宽搜思想)

    Find The Multiple Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 24768   Accepted: 102 ...

  5. poj1426 Find The Multiple

    Find The Multiple Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 14622   Accepted: 593 ...

  6. 搜索:POJ2251&POJ1426&POJ3087&POJ2488

    图的遍历也称为搜索,就是从图中某个顶点出发,沿着一些边遍历图中所有的顶点,且每个顶点仅被访问一次,遍历可采取两种不同的方式:深度优先搜索(DFS)和广度优先搜索(BFS). 1.DFS算法思想` 从顶 ...

  7. Find The Multiple (poj1426 一个好的做法)

    Find The Multiple Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 16505   Accepted: 673 ...

  8. poj1426 Find The Multiple(c语言巧解)

    Find The Multiple Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 36335   Accepted: 151 ...

  9. POJ-1426.Findthemultiple.(BFS)

    一开始模拟了一波大数取余结果超时了,最后改成long long过了emmm... 本题大意:给出一个200以内的数n,让你找出一个m使得m % n == 0,要求m只有1和0组成. 本题思路:BFS模 ...

  10. POJ1426:Find The Multiple(算是bfs水题吧,投机取巧过的)

    http://poj.org/problem?id=1426 Description Given a positive integer n, write a program to find out a ...

随机推荐

  1. java文档 第十一章 其他考量-b

    Finalization 和弱引用.软引用.虚引用 Finalization and Weak, Soft, and Phantom References Some applications inte ...

  2. CSS/JQuery元素选择器之&amp;&amp;和||,选择器的逻辑操作

    使用CSS或JQuery选中元素的时候.非常多时候我们须要对条件进行&&或者||操作. JQuery或者CSS中的||操作是非经常常使用的.也非常easy,就是通过逗号来分隔的. se ...

  3. unity, StopAllCoroutines导致bug的解决办法

    StopAllCoroutines有时候不用不行. 但只要一用,就可能导致无穷无尽的bug. 原因是StopAllCoroutines会将当前脚本中所有coroutines都停掉,而没法做到只停掉我们 ...

  4. Hadoop-2.4.0分布式安装手冊

    文件夹 文件夹 1 1. 前言 2 2. 部署 2 2.1. 机器列表 2 2.2. 主机名 2 2.2.1. 暂时改动主机名 3 2.2.2. 永久改动主机名 3 2.3. 免password登录范 ...

  5. js arguments 内置对象

    1.arguments是js的内置对象. 2.在不确定对象是可以用来重载函数. 3.用法如下: function goTo() { var i=arguments.length; alert(i); ...

  6. Hello,Ajax

    学习了Ajax技术,写了一个最简单的Ajax应用 <%@page contentType="text/html; charset=utf-8" language=" ...

  7. java printf long

    System.out.printf("%d\n", 1000000000000000000L); 

  8. 如何在uboot上实现从网络下载版本镜像并直接在内存中加载之?

    这是作者近期项目上遇到的一个需求,描述如下: 一块MT7620N的路由器单板,Flash中已存放一个版本并可以通过uboot正常加载并启动.现在需要:在uboot上电启动过程中,通过外部按键触发干涉, ...

  9. hdu6070 Dirt Ratio 二分+线段树

    /** 题目:hdu6070 Dirt Ratio 链接:http://acm.hdu.edu.cn/showproblem.php?pid=6070 题意:给定n个数,求1.0*x/y最小是多少.x ...

  10. Iptables规则执行顺序详解

      1.The first is the mangle table which is responsible for the alteration of quality of service bits ...