题目概述:
给定一个自然数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 }