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

  1. 2
  2. 6
  3. 19
  4. 0

Sample Output

  1. 10
  2. 100100100100100100
  3. 111111111111111111

思路:

1. 抽象成背包, 把0,1 串具体化, 变成 1, 10, 100, 1000

这里有两个好处:

第一, 每个数字都是唯一的, 任何数字不是另一个数字的前导, 抽象成背包问题

第二, 任何01串都可以用上述的数字表示出来. 比如, 111 = 100 + 10 + 1, 1110 = 1000+ 111

上面这个技巧, 在背包问题的一个优化中讨论过. 非常巧妙

2. dp[i][j] 表示前 i 个(1, 10, 100... 10^i) 组成的数字模 n 的余数 j 的最小值, 当该最小值不存在时, dp[i][j] = 0

  比如, 当 n = 6 时, dp[1][4] = 10. dp[1][5] = 11. dp[2][2] = 110

3. dp[i][j] = min(dp[i-1][j], dp[i-1][r]+10^i), 其中 r 也是余数, 当 j 等于0 且 dp[i][j] 不等于 0 时, 得到解

  表示以 上一层 (i-1) 的余数 r 作为支点更新 dp[i][j], 原理是:

  已知 r = dp[i-1][r]%n

  dp[i][(r + 10^i)%N] = dp[i-1][r] + 10^i 其中 j = (r + 10^i)%N

4. (3) 的求解过程中每次求解 (10^i)%n 太过复杂, 可以根据模定理进行优化

  定理: (a%n + b%n)%n == (a+b)%n, (a%n * b%n)%n == (a*b)%n

  可以使用上述定理简化以减少计算量

  比如, 已知 10%6 == 4, 那么 100%6 == (10*10)%6 == (10%6*10%6)%6 == (4*10%6)%6 == (4%6*10%6)%6 == (4*10)%6 == 4

  1000%6 == (100*10)%6 == (100%6*10%6)%6 == (4*10%6)%6 == 4

总结:

1. 发现一个错误: 一样的代码, 返回不一样的结果. 原因: int 越界

  1. exp *= 10;
  2. rem = (rem * 10) % n; // 模运算定理
  3. printf("exp = %lld, rem = %d\n", exp,rem);

  返回的是 10, 4 (correct)

但是

  1. exp *= 10;
  2. rem = (rem * 10) % n; // 模运算定理
  3. printf("exp = %d, rem = %d\n", exp,rem);

  返回的总是 10, 0 (wrong)

2. 任意的01串转化为1, 10, 100... 的组合, 从而抽象为01背包. 同时使用了一个简化计算 10^i 的技巧, 使得3个小时才看懂50行代码

代码:

代码写的不能再精髓了, 我了解思路后开始码, 但改过来改过去, 越改越觉得下面的代码精髓

1. 初始化, dp[i][r] == 0 表示没有满足条件的数, 同时省去了 dp[0][0] 的赋值

2. 17, 18, 23, 24行的代码, 保证了 min

3. 21 行, r==0 时的特殊性, 只有 r=0 时, 才能增加一个值

  1. #include <iostream>
  2. using namespace std;
  3.  
  4. const int MAXN = 210;
  5. int n;
  6. long long int dp[MAXN][MAXN];
  7. /*
  8. * dp[i][r] 表示前 i 个数组成的数字模 n 等于 r 的最小值
  9. * dp[i][r] = min(dp[i-1][r], dp[i][r']+10^i) 以 r' 为支点更新 dp[i][r]
  10. */
  11. long long int solve_dp() {
  12. dp[0][1] = 1;
  13. long long int rem = 1, exp = 1;
  14. for(int i = 1; i < MAXN; i ++) {
  15. exp = exp*10;
  16. rem = (rem*10)%n;
  17. for(int r = 0; r < n; r ++) // 继承
  18. dp[i][r] = dp[i-1][r];
  19.  
  20. for(int r = 0; r < n; r ++) {
  21. if(dp[i-1][r] || r == 0) { //r == 0 比较特殊, 唯一一个可能用于更新的状态的值, 即使 dp[i-1][r] = 0, 去求 dp[i][r] 仍是必要的
  22. long long int newr = (r + rem)%n;
  23. if(dp[i][newr] == 0)
  24. dp[i][newr] = exp + dp[i-1][r]; // 首次更新, 保证了最小性
  25. if(newr == 0)
  26. return dp[i][0];
  27. }
  28. }
  29. }
  30. }
  31. int main() {
  32. freopen("E:\\Copy\\ACM\\测试用例\\in.txt", "r", stdin);
  33. while(cin >> n && n != 0) {
  34. if(n == 1)
  35. cout << 1 << endl;
  36. else
  37. cout << solve_dp() << endl;
  38. }
  39. return 0;
  40. }

  

update 2014年3月14日21:00:58

1. r = 0 时的特殊性. r = 0 的特殊性体现在 dp[i][0] = 0 和 余数为 0 的双重意义.  余数为 0 表示不存在某个数对 n 取模为 0. 而 dp[i][0] = 0 又起到了初始化的作用, 使得对于一个数, 比如 100, dp[i][100%n] = 0 + 100. 这个 0 就用 dp[i][0] 取代了, 相当于代码重用

POJ 1426 Find The Multiple(背包方案统计)的更多相关文章

  1. POJ 3093 Margaritas(Kind of wine) on the River Walk (背包方案统计)

    题目 Description One of the more popular activities in San Antonio is to enjoy margaritas in the park ...

  2. 广搜+打表 POJ 1426 Find The Multiple

    POJ 1426   Find The Multiple Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 25734   Ac ...

  3. POJ 1426 Find The Multiple --- BFS || DFS

    POJ 1426 Find The Multiple 题意:给定一个整数n,求n的一个倍数,要求这个倍数只含0和1 参考博客:点我 解法一:普通的BFS(用G++能过但C++会超时) 从小到大搜索直至 ...

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

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

  5. POJ.1426 Find The Multiple (BFS)

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

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

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

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

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

  8. POJ 1426 Find The Multiple(数论——中国同余定理)

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

  9. POJ 1426 - Find The Multiple - [DP][BFS]

    题目链接:http://poj.org/problem?id=1426 Given a positive integer n, write a program to find out a nonzer ...

随机推荐

  1. scrollTop兼容封装

    <!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8&quo ...

  2. python+spark程序代码片段

    处理如此的字符串: time^B1493534543940^Aid^B02CD^Aasr^B叫爸爸^Anlp^B{"domain":"com.abc.system.cha ...

  3. 带limit的hivesql排序

    带limit的hivesql排序   select requestdomain,count(1) as cnt from ods_cndns_real_log where dt = 20160707 ...

  4. less css框架的学习

    什么是LESSCSS LESSCSS是一种动态样式语言,属于CSS预处理语言的一种,它使用类似CSS的语法,为CSS的赋予了动态语言的特性,如变量.继承.运算.函数等,更方便CSS的编写和维护. LE ...

  5. iptables进行DNAT(目标地址转换)

    前言:对于Linux服务器而言,一般服务器不会直接提供公网地址给用户访问,服务器在企业防火墙后面,通常只是暴露一个公网给用户,下面已80端口进行实现. 演示环境:VM (1)host: 172.16. ...

  6. JavaScript高级 面向对象(7)--深拷贝与浅拷贝

    说明(2017.3.31): 1. 画图: var car = {name:"法拉利"}; var p = {name: "张三", age: "19 ...

  7. (function($){...})(jQuery)是什么意思?

    本文转自:http://blog.csdn.net/rambo_china/article/details/7742321 最近在工作中看到这调用定义方法,并且同时调用的方式,觉得很疑惑,看到这篇博客 ...

  8. valgrind: failed to start tool 'memcheck' for platform 'amd64-linux

    valgrind运行错误 问题描述 valgrind运行时,无法找到相关工具文件,具体报错如下 valgrind: failed to start tool 'memcheck' for platfo ...

  9. BeamNG.drive物理引擎评鉴

    BeamNG.drive是一款由BeamNG公司开发并于2013年首次发布的软体物理模拟游戏.作为模拟游戏,特别是物理模拟的粉丝,我早早就开始使用BeamNG.drive.我立即对崩溃的准确性和细节印 ...

  10. Flume1.5.0入门:安装、部署、及flume的案例

    转自:http://www.aboutyun.com/thread-8917-1-1.html 问题导读1.什么是flume2.flume的官方网站在哪里?3.flume有哪些术语?4.如何配置flu ...