加油 ( •̀ ω •́ )y!

51Nod 1109 01组成的N的倍数

题目概述:

给定一个自然数N,找出一个M,使得M > 0且M是N的倍数,并且M的10进制表示只包含0或1。求最小的M。
 
例如:N = 4,M = 100。
Input
输入1个数N。(1 <= N <= 10^6)
Output
输出符合条件的最小的M。
Input示例
4
Output示例
100

思路:  因为每一次都只有0或者1两个选择,并且m的位数由1位逐次递增,我们就可以用广度优先搜索的方式逐层拓展求出最先得到的那个M 即为最小的N的倍数。由于题目只说明M>=1,并未指明上限
   M可能远远超出long long 的范围,所以我们用对N的余数来判断当前的M是否满足,在存储余数的同时我们需要存储M的状态保证找到结果时能正确输出M;在这里我们还需要做一个优化就是,对于
  已经出现过的余数,在拓展下去也是无用,所以我们保证每个余数只出现一次,这样就大大的优化了时间!好了话不多说直接上代码

代码如下:
 1 #include<iostream>
 2 #include<algorithm>
 3 #include<cstring>
 4 #include<queue>
 5 #include<string>
 6 
 7 using namespace std;
 8 const int maxn = 5e6;
 9 struct node{
10     string str;//用于储存当前的M状态
11     int data;//存储当前对n的余数
12 };
13 bool vis[maxn];//用于剪枝 避免重复计算 浪费时间
14 queue<node>Q;
15 int n;
16 void BFS()
17 {
18     memset(vis,0,sizeof(vis));
19     node e;
20     e.str='1';//首位肯定为1
21     e.data=1;
22     Q.push(e);
23     vis[1]=1;
24     while(!Q.empty())
25     {
26         node q=Q.front();
27         Q.pop();
28         if(q.data%n==0)
29         {
30             cout<<q.str<<endl;
31             return;
32         }
33         for(int i=0;i<=1;i++)
34         {
35             node p=q;
36             if(!vis[(q.data*10+i)%n])//剪枝步骤
37             {//判断余数是否出现过了,若出现过了再延伸下去也是无用
38                 char c=i+'0';
39                 p.data=(q.data*10+i)%n;//保存新添加一个数后对n的余数
40                 p.str.push_back(c);
41                 Q.push(p);
42                 vis[p.data]=1;//标记为已经出现过
43             }
44         }
45     }
46 }
47 int main()
48 {
49     while(cin>>n)
50     {
51         if(n==1)cout<<"1"<<endl;
52         else BFS();
53     }
54     return 0;
55 }

 

posted @ 2017-11-13 15:46  皮皮虎  阅读(796)  评论(0编辑  收藏  举报