POJ 1426 Find The Multiple

题意:给定一个整数n,求n的一个倍数,要求这个倍数只含0和1

参考博客:点我

解法一:普通的BFS(用G++能过但C++会超时)

    从小到大搜索直至找到满足条件的数,注意最高位一定为1

    假设 n=6  k即为当前所求的目标数,不满足条件则进一步递推 (i 为层数(深度),在解法二的优化中体现,此时可以不管)


    1%6=1 (k=1)  i=1
    {
      (1*10+0)%6=4 (k=10)  i=2
      {
        (10*10+0)%6=4 (k=100)  i=4
        {
          (100*10+0)%6=4 (k=1000)  i=8
          (100*10+1)%6=5 (k=1001)  i=9
        }
        (10*10+1)%6=5 (k=101)  i=5
        {
          (101*10+0)%6=2 (k=1010)  i=10
          (101*10+1)%6=3 (k=1011)  i=11
        }
      }

      (1*10+1)%6=5 (k=11)  i=3
      {
        (11*10+0)%6=2 (k=110)  i=6
        {
          (110*10+0)%6=2 (k=1100)  i=12
          (110*10+1)%6=3 (k=1101)  i=13
        }
        (11*10+1)%6=3 (k=111)  i=7
        {
          (111*10+0)%6=0 (k=1110)  i=14 有解
          (111*10+1)%6=1 (k=1111) 由于前面有解,这个余数不存储
        }
      }
}

可以看到,如此反复枚举下去,直至找到目的数k为止,注意若当前k不满足条件,则将k*10 和k*10 + 1入队以便进一步判断

以下是解法一的代码,用G++能过,但用C++超时(我是在hust交的),不知道为什么!

/* POJ 1426 Find The Multiple BFS 用C++超时但G++过了*/
#include <cstdio>
#include <queue>
using namespace std; /*返回最大能整除n的只有1和0组成的数*/
long long bfs(int n){
long long tmp;
queue<long long> q;
q.push();
while (!q.empty()){
tmp = q.front();
q.pop();
if (tmp % n == ){
return tmp;
}
q.push(tmp * );
q.push(tmp * + );
}
return ;
} int main()
{
int n;
while (scanf("%d", &n) == && n){
printf("%lld\n", bfs[n]);
} return ;
}

解法二:优化的BFS(C++能过)

由于C++超时,于是我参考了以下别人的代码,地址上面已给出,但为了加深记忆,还是自己写一遍!

同余定理的应用:

        (a+b)%n = (a%n + b%n)%n

        (a*b)%n =  (a%n * b%n)%n

在解法一中,由于一直*10, k有可能出现越界,具体请参考原博客,在这里只写余数优化过程:

取解法一中的任意式子:

  前一层: mod =  (11*10 + 0)%6 = 2, k = 110, i = 6, k % 6 = 2

  后一层: mod = (k'*10 + 0) %6   //注意这里的k'为上一层的k,即110, 另此层k为110*10 + 0, i 为6 * 2

           =( (k'*10)%6 + 0%6 ) % 6

         =( (k'%6 * 10%6) % 6 + 0%6) % 6   //k'%6即为上一层的mod,记为mod', 在这个例子中就是2, 另k'%6 = mod' = mod'%6

           =( (mod'6 * 10%6) % 6 + 0%6) % 6

         =( (mod' * 10) % 6 + 0 % 6) % 6

         = (mod'*10 + 0) % 6;  //即当前层的mod=前一层的mod*10 + 0 (具体是0还是1和i有关) 因为0、1是循环取的

为了加强理解,再推导一遍i为奇数的过程

  前一层:mod =  (11*10 + 0)%6 = 2, k = 110, i = 6, k % 6 = 2

  后一层:  mod = (k'*10 + 1)  % 6   //此层 k = 110*10+1, i 为6*2+1

          = ( (k'%6 * 10%6) % 6 + 1 % 6) % 6

          = ( mod' * 10 + 1) % 6  //即当前层的mod=前一层的mod*10 + 1(具体是0和1和i有关)

这样就化简了求模的过程,共经过i步求模获得当前的目标数k % n = 0(但此时并不知道k具体的值),只知道求mod的过程

要通过操作数获取k,我是这样理解的:

  经过i步得到满足条件的数k(尽管k暂时还不知道), 由于每个数会产生两个分支,即k是由 i / 2 层的数k'递推而来的。 即 k'/2 * 2 + 0或1. 因此要知道k的末位是0还是1只要考虑当前k的奇偶性,因为2 * i / 2一定是偶数,奇偶性就是由后面的1或者0来决定的!如果是奇数,则证明当前k的最后一位是1,否则是0,值得注意的是:k的奇偶性和i的奇偶性恰巧是相同的,由于每个数会产生两个新的数字,可以看成是一棵二叉树, 如图:

结点编号即为获取当前k(括号里的数)所需要的操作步数,可以看到k与编号的奇偶性是恰好相同的,因此利用操作步数i, 循环i%2 与i/ = 2 就可以获取目标数的各个位(注意是从叶子到根得到的各个位置上的数(即先得到后面的位的数),因此输出时需要到过来),

优化后的BFS的代码:

/* POJ 1426 Find The Multiple BFS 优化*/
#include <cstdio> int mod[]; //寸模,参考别人的计算这是最小的AC下限 int main()
{
int n;
while (scanf("%d", &n) == && n){
mod[] = ;
int i;
for (i = ; mod[i - ] != ; ++i){
//该公式前面已证明, 注意:i为奇偶数分别对应 i%2 = 1和0
mod[i] = (mod[i/] * + i % ) % n; // i/2为前一层
}
--i; //i此时为取模的次数
int p = ;
while (i){
mod[p++] = i % ; //操作次数转化成所要的数--->k(可用二叉树理解)
i /= ;
}
while (p){
printf("%d", mod[--p]); //逆序输出即为目的数
}
printf("\n");
} return ;
}

解法三: 这题还可以用DFS通过控制递归深度直接过

/* POJ 1426 Find The Multiple --- DFS */
#include <cstdio> int n;
bool flag; void dfs(unsigned long long tmp, int i){
if (flag || i > )
return;
if (tmp % n == ){
flag = ;
printf("%llu\n", tmp);
return ;
}
else{
dfs(tmp * , i+);
dfs(tmp * + , i+);
}
} int main()
{
while (scanf("%d", &n) == && n){
flag = ;
dfs(,);
} return ;
}

POJ 1426 Find The Multiple --- BFS || DFS的更多相关文章

  1. POJ 1426 Find The Multiple (DFS / BFS)

    题目链接:id=1426">Find The Multiple 解析:直接从前往后搜.设当前数为k用long long保存,则下一个数不是k*10就是k*10+1 AC代码: /* D ...

  2. poj 1426 Find The Multiple (bfs 搜索)

    Find The Multiple Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 18012   Accepted: 729 ...

  3. POJ - 1426 Find The Multiple 【DFS】

    题目链接 http://poj.org/problem?id=1426 题意 给出一个数 要求找出 只有 0 和 1 组成的 十进制数字 能够整除 n n 不超过 200 十进制数字位数 不超过100 ...

  4. POJ 1426 Find The Multiple (dfs??!!)

    Description Given a positive integer n, write a program to find out a nonzero multiple m of n whose ...

  5. POJ 1426 Find The Multiple BFS

    没什么好说的 从1开始进行广搜,因为只能包涵0和1,所以下一次需要搜索的值为next=now*10 和 next=now*10+1,每次判断一下就可以了,但是我一直不太明白我的代码为什么C++提交会错 ...

  6. poj 1426 Find The Multiple ( BFS+同余模定理)

    Find The Multiple Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 18390   Accepted: 744 ...

  7. DFS/BFS(同余模) POJ 1426 Find The Multiple

    题目传送门 /* 题意:找出一个0和1组成的数字能整除n DFS:200的范围内不会爆long long,DFS水过~ */ /************************************ ...

  8. POJ.1426 Find The Multiple (BFS)

    POJ.1426 Find The Multiple (BFS) 题意分析 给出一个数字n,求出一个由01组成的十进制数,并且是n的倍数. 思路就是从1开始,枚举下一位,因为下一位只能是0或1,故这个 ...

  9. POJ 1426 Find The Multiple(寻找倍数)

    POJ 1426 Find The Multiple(寻找倍数) Time Limit: 1000MS    Memory Limit: 65536K Description - 题目描述 Given ...

随机推荐

  1. MonoRail学习:可重复组件ViewComponents的使用

    在MonoRail中我们可以定义一些可重用的组件,在其他需要使用的页面引入这个组件就可以了.有点相当于.NET中的自定义控件,可以节约代码,方便开发,提高重用性. 在MonoRail中把这一功能叫做V ...

  2. Matlab与C/C++联合编程之Matlab以MEX方式调用C代码(五)完整过程加示

    如下为本人亲证代码: 一: 编译器的安装与配置(环境不同,显示结果不同) 要使用MATLAB编译器,用户计算机上应用事先安装与MATLAB适配的以下任何一种ANSI C/C++编译器: 5.0.6.0 ...

  3. Bootstrap非常简单实用的web前端开发框架

    今天无意间用firebug看网站的代码发现了Bootstrap,之前从来没有听说过这个东东,于是对它产生了好奇感,通过百度我了解到了Bootstrap是一款非常简单,强悍,实用,移动设备端优先使用的这 ...

  4. URAL 1306 Sequence Median(优先队列)

    题意:求一串数字里的中位数.内存为1M.每个数范围是0到2的31次方-1. 思路:很容易想到把数字全部读入,然后排序,但是会超内存.用计数排序但是数又太大.由于我们只需要第n/2.n/2+1大(n为偶 ...

  5. vc设置按钮文字颜色

    设置按钮文字颜色使用 CMFCBUTTON即可 在OnInitDialog函数加入如下内容即可 ((CMFCButton*)GetDlgItem(IDC_MFCBUTTON1))->SetTex ...

  6. python中的面向对象编程

    在python中几乎可以完成C++里所有面向对象编程的元素. 继承:python支持多继承: class Derived(base1, base2, base3): pass 多态:python中的所 ...

  7. N个元素组成二叉树的种类

    <算法>中的二叉查找树一节的一道习题. N个元素组成的二叉树固定一个根节点,这个根节点的左右子树组合数为(0,n-1),(1,n-2),(2,n-3)...(n-1,0),假设N个元素组成 ...

  8. POJ 3278 经典BFS

    进一步了解了bfs; 题意:给你n,然后用+,-,*三种运算使n变成k; 漏洞:在算出新的数字之后,一定要判边界,否则RE,而且在每一步后面都得加判断是否等于K,如果是即刻退出,否则WA,判这个的时候 ...

  9. array_intersect() php筛选两个数组共有的元素

    我们已经讲过如何筛选出连个数组中不共有的元素,今天就来看看php如何筛选出两个数组中共有的元素,例如筛选$array1和$array2共有的元素. 函数名:array_intersect(): 调用方 ...

  10. PHP 上传图片和安全处理

    上传图片 public function images() { $data = $_FILES['file']; switch($data['type']) { case 'image/jpeg': ...