0-K Multiple
Time limit: 1000 ms
Memory limit: 128 MB
Memory limit: 128 MB
You are given an integer NN and a digit KK. Find the smallest multiple of NN that consists only of digits KK and 00.
Standard input
The first line contains two integers NN and KK.
Standard output
Print the result on a single line.
Constraints and notes
- 1 \leq N \leq 10^51≤N≤105
- 1 \leq K \leq 91≤K≤9
Input | Output |
---|---|
5 2 | 20 |
7 4 | 4004 |
13 7 | 7007 |
这里要推荐一下这个网站(CS Academy),这个网站的出题都是直接对于题意进行描述而不会写一大堆的题目背景什么的。极力推荐大家在这个网站练习,看题目很舒服的!!!
对于这道题,题意也很容易看,就是让你求出只由0跟k(1-9)组成的最小的n的倍数。
做法:通过显然DFS的做法是行不通的,看到这道题,很容易就想到的做法是BFS,从小到大构建由0跟数字k组成的数,再验证是否是n的倍数。
但是,直接这样处理显然是行不通的,首先这个数是可能超过long long 的范围的,直接BFS遍历所有的数是行不通的,这里我们可以发现,如果两个数x,y与n同余,根据BFS的方式得到的下两个数分别是x * 10 与 x * 10 + k,与y * 10 与 y * 10 +k ,肯定也是一样的,所以对于BFS来说,这两种可以归类为同意个状态!
简言之,我们其实可以把每一个由0跟k组成的数%n作为一个状态,那样我们最多就只需枚举n个状态了!但是题目要求的是原本的由0跟k组成的数,而不是取模后的数,所以我们在取模的时候还是要保存每一个状态原本的数,这里可以利用一个map映射,即每一个%n后的状态映射他原本的数,这个才是我们要的答案啦,晚上还有另一种方法,是通过记录BFS过程中的路径,这样也是可以的。
代码如下:
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <stack>
#include <map>
#include <set>
#include <utility>
#include <vector>
#include <queue>
#include <cstdlib>
#define ll long long
#define ull unsigned long long
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define repn(i,b,a) for(int i=b;i>=a;i--)
#define mt(a,x) memset(a,x,sizeof(a))
using namespace std;
const int maxn = 500050;
const int mod = 1e9+7;
const double pi = acos(-1.0);
int n,k;
int vis[maxn];
char s[] = {'0','1','2','3','4','5','6','7','8','9'}; //对k进行字符化处理
map<int,string> mp;
void BFS(){
queue<int> qu;
qu.push(k);
mp[k] = s[k];
while(!qu.empty()){
int now = qu.front();
qu.pop();
if(now%n==0){
cout << mp[now] << endl;
return ;
}
if(!vis[now*10%n]){
vis[now*10%n] = 1;
qu.push(now*10%n);
mp[now*10%n] = mp[now]+s[0]; //保存原数
}
if(!vis[(now*10+k)%n]){
vis[(now*10+k)%n] = 1;
qu.push((now*10+k)%n);
mp[(now*10+k)%n] = mp[now]+s[k];
}
}
}
int main() {
ios::sync_with_stdio(false);
cin >> n >> k;
BFS();
}