HDU 1664 Different Digits (数论 -- 鸽笼原理 + BFS搜索 + 余数判重)
来源:互联网 发布:vb.net和c#区别 编辑:程序博客网 时间:2024/06/05 03:52
大体题意:
给你一个数字n,让你找出它的一个倍数m,使得m中不同的数字尽可能的少,如果有多解,输出最小的一个!
思路:
肯定是搜索的题目,我们得先考虑数字m 不同数字的种类个数,以便缩小搜索范围。
这里巧妙的运用了鸽笼原理,举个简单的小例子来说明这个原理,如果让你选择一个月份的话,你选择13次肯定有两次是重复的,这个题目同样也是,我们选择n+1个数字,肯定有两个数对n取模是相同的。我们这样的数取由1种数字组成!
那么num1 = AAAAAAAAA
num2 = AAAA
那么num1 - num2肯定是n的倍数 num1 - num2 = AAAA00000的形式!
所以说最多两种数字就一定有解!!!
那么肯定先搜索由1种数字组成的,在搜索两种数字组成的!
有两个剪枝:
1.搜到目前为止,字符串长度已经长于已经更新好的答案了 直接return了!
2.搜到当前数字对n 取模与之前重复的话,就不搜了。
这个很好理解:
先想搜索1种数字的,当你取模完后 值于之前重了,那么你下一步取模 肯定也会重复,因此形成循环!
在想想搜索2种数字的,如果下一步取模方式与之前一样的话,肯定是循环的,不用搜!
如果方式不同那么就可以由前面的那个位置继续搜!
因此 只要余数重复就停止搜索!
这里也有一些技巧:
因为搜索两种数字 时 得记录字符串前指针,因此这里bfs 手写队列会比queue好很多,还省了不少空间!
#include <cstdio>#include <cstring>#include <algorithm>#include <queue>#include <string>using namespace std;const int inf = 0x3f3f3f3f;struct Node{ char ch; int mod; int la; int len;}qq[1000000];int head,tail;int anslen = inf;int num[10],n;bool vis[65540];string res;bool bfs1(int k){ memset(vis,0,sizeof vis); int v = 0; string ans = ""; int len2 = 0; while(1){ ans += '0' + k; ++len2; if (len2 > anslen)return false; v = (v * 10 + k) % n; if (!v){ if (anslen == inf || ans.length() < anslen || (ans.length() == anslen && ans < res)){ res = ans; anslen = ans.length(); return 1; } return 0; } if (vis[v])return 0; vis[v] = 1; }}void dfs(string& ans,int cur){ if (~cur)dfs(ans,qq[cur].la); else { return ; } ans += qq[cur].ch;}bool bfs2(int num1,int num2){ memset(vis,0,sizeof vis); head = tail = 0; int flag = 0; if (num1){ qq[tail].ch = num1 + 48; qq[tail].mod = num1 % n ; qq[tail].len = 1;// vis[qq[tail].mod ] = 1; qq[tail++].la = -1; } qq[tail].ch = num2 + 48; qq[tail].mod = num2 % n ; qq[tail].len = 1;// vis[qq[tail].mod ] = 1; qq[tail++].la = -1; num[0] = num1, num[1] = num2; while(head < tail){ if (qq[head].len > anslen)return false; if (vis[qq[head].mod ]){ ++head; continue; } vis[qq[head].mod ] = 1; if (qq[head].mod == 0){ string ans = ""; dfs(ans,head);//// if (ans == "16")puts("haha"); if (anslen == inf || ans.length() < res.length() || (ans.length() == res.length() && ans < res)){ res = ans; anslen = ans.length(); return 1; } return 0; } for (int i = 0; i < 2; ++i){ int mod = (qq[head].mod * 10 + num[i]) % n;// if (vis[mod])break;// vis[mod] = 1; qq[tail].ch = num[i] + 48; qq[tail].mod = mod; qq[tail].len = qq[head].len+1; qq[tail++].la = head; } ++head; } return 0;}int main(){ while(~scanf("%d",&n) && n){ bool ok = 0; res = ""; anslen = inf; for (int i = 1; i < 10; ++i){ if (bfs1(i)){ ok = 1; } } if (ok){ printf("%s\n",res.c_str()); continue; } for (int i = 0; i < 10; ++i){ for (int j = i + 1; j < 10; ++j){ if (bfs2(i,j)){ ok = 1; } } } printf("%s\n",res.c_str()); } return 0;}
Different Digits
Time Limit: 10000/4000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 1580 Accepted Submission(s): 445
Problem Description
Given a positive integer n, your task is to find a positive integer m, which is a multiple of n, and that m contains the least number of different digits when represented in decimal. For example, number 1334 contains three different digits 1, 3 and 4.
Input
The input consists of no more than 50 test cases. Each test case has only one line, which contains a positive integer n ( 1<=n < 65536). There are no blank lines between cases. A line with a single `0' terminates the input.
Output
For each test case, you should output one line, which contains m. If there are several possible results, you should output the smallest one. Do not output blank lines between cases.
Sample Input
7 15 16 101 0
Sample Output
7555161111
Source
2004 Asia Regional Shanghai
Recommend
xhd
0 0
- HDU 1664 Different Digits (数论 -- 鸽笼原理 + BFS搜索 + 余数判重)
- BFS+余数判重+数论 hdu-1664-Different Digits
- (HDU 1664)Different Digits BFS + 数论 + 余数判重 详细题解
- hdu 1664 Different Digits(bfs+余数判重)
- hdu 1664 Different Digits (bfs+取余判重+数论知识)
- HDU-1664-Different Digits(BFS)
- HDU1664 Different Digits(bfs +数论剪枝)
- poj1465Multiple(经典BFS+余数判重)
- 【搜索】 HDU 1664 Different Digits
- hdu 4474 Yet Another Multiple Problem (余数判重 + BFS)
- HDU 4474&&POJ 1465 BFS&&余数判重
- hdu 2579 余数判重
- hdu1226 超级密码(bfs+余数判重)
- 【hdu】1664 different digits【搜索+字符串处理】
- uva 1341 - Different Digits(数论+bfs)
- Poj1465 Multiple(BFS+余数判重)
- POJ 1465 Multiple BFS + 余数判重
- poj 1465 bfs+余数判重
- Android复习之旅--ContentProvider
- 如何利用SQL Server With As递归获取层级关系数据
- 机器学习(五):SVM支持向量机_Python
- CodeForces 37d
- TypeError: view must be a callable or a list/tuple in the case of include().
- HDU 1664 Different Digits (数论 -- 鸽笼原理 + BFS搜索 + 余数判重)
- 常见对象_把int数组拼接成字符串的案例改进版
- ubuntu 源码安装java
- FCN 简单梳理
- mybatis 插入递增主键——abc201611090001 abc201611090002
- log信息输出到文件
- MVC框架的简单描述
- S5PV210体系结构
- android 中的色彩矩阵和图像分析