洛谷P1602 Sramoc问题 题解报告【同余+bfs】

题目描述

话说员工们整理好了筷子之后,就准备将快餐送出了,但是一看订单,都傻眼了:订单上没有留电话号码,只写了一个sramoc(k,m)函数,这什么东西?什么意思?于是餐厅找来了资深顾问团的成员,YQ,SC,HQ,经过大量的查阅,大家获得了一些信息,Sramoc ( K , M ) 表示用数字0、1、2…、K-1组成的自然数中能被M整除的最小数。例如 K=2,M=7的时候,Sramoc( 2 , 7 ) = 1001。自然电话号码就是1001,为了尽快将快餐送出,电脑组的童鞋们埋头算起了这个齐葩的号码。。。

输入输出格式

输入格式:

第1行为两个整数 k, m (2≤k≤10, 0≤m≤1000)。

输出格式:

仅1行,那个电话号码(最小的数)。

输入输出样例

输入样例#1:
2 7
输出样例#1:
1001












题解


很容易想到直接暴搜,也很明显这是错的,因为结果可能很大,长整型都不一定装的下
但我们先看看bfs暴搜的思路:

先1~K-1入队,每次取出一个数x,对x对M取余看看是不是0,是就输出结束算法,否则x=x*10,将末位加上0~K-1分别加入队列继续搜索


显然这样做效率很低,先不说长整型装不装得下,状态就有K^a【a为答案的位数】,无法承受。

同余

根据同余的思想,对于+和*操作,在中途取余对结果没有影响,所以我们在过程中将x对M取余,这样子x最多有M个,时间复杂度也就变成了O(M)。
为了输出最终的结果,我们还需要开一个队列储存当前的数串【我用vector实现的】


#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<vector>
#include<algorithm>
#define LL long long int
using namespace std;
const int maxn=1005,INF=2000000000,P=1000000007;

int K,M;
bool vis[maxn];

void bfs(){
	queue<LL> q;
	queue<vector<int> > q2;
	vector<int> s;
	for(int i=1;i<K;i++){
		q.push(i%M);
		vis[i%M]=true;
		s.push_back(i);
		q2.push(s);
		s.pop_back();
	}
	LL u,k;
	while(!q.empty()){
		u=q.front();
		q.pop();
		s=q2.front();
		q2.pop();
		for(int i=0;i<K;i++){
			k=(u*10+i)%M;
			s.push_back(i);
			if(!k){
				for(unsigned int j=0;j<s.size();j++) printf("%d",s[j]);
				cout<<endl;
				return;
			}
			else if(!vis[k]){
				vis[k]=true;
				q.push(k);
				q2.push(s);
			}
			s.pop_back();
		}
	}
}

int main(){
	cin>>K>>M;
	bfs();
	return 0;
}


posted @ 2017-09-12 14:02  Mychael  阅读(285)  评论(0编辑  收藏  举报