洛谷 1602 Sramoc问题
Description
话说员工们整理好了筷子之后,就准备将快餐送出了,但是一看订单,都傻眼了:订单上没有留电话号码,只写了一个sramoc(k,m)函数,这什么东西?什么意思?于是餐厅找来了资深顾问团的成员,YQ,SC,HQ,经过大量的查阅,大家获得了一些信息,Sramoc ( K , M ) 表示用数字0、1、2…、K-1组成的自然数中能被M整除的最小数。例如 K=2,M=7的时候,Sramoc( 2 , 7 ) = 1001。自然电话号码就是1001,为了尽快将快餐送出,电脑组的童鞋们埋头算起了这个齐葩的号码。。。
Input
第1行为两个整数 k, m (2≤k≤10,0≤m≤1000)。
Output
仅1行,那个电话号码(最小的数)。
Sample
输入样例#1:
2 7
输出样例#1:
1001
Solution
我觉得这道题有点神奇
暴力会超时(比如极端数据2 999)
深搜也会超时,因为没有办法判断是不是最小的,必须搜完
可以用宽搜
把已经得到的数放在一个队列里面,每次取出一个,然后在后面接一个数
因为可以在乘法和加法的时候取模,所以最多会有m个数
数位是从高位到低位的,枚举是从小到大的,所以第一次找到余数为0的时候,那个数是最小的
因为要输出这个数,所以我用了一个链表,方便新加数,并且被转移到的数可以直接利用转移的数
#include<algorithm> #include<iostream> #include<cstring> #include<cstdlib> #include<cstdio> #include<cmath> #define lo long long using namespace std; int q[1011],fir[1011],nxt[1011],to[1011],out[101],k,m,e=0; bool ex[1011]; int read() { int ans=0,f=1;char ch=getchar(); while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();} while(isdigit(ch)) {ans=ans*10+ch-'0';ch=getchar();} return ans*f; } void solve() { int h=1,t=0,o,lim,zc; q[++t]=0;ex[0]=1; while(h<=t) { o=q[h++]; lim=o==0? 1:0; for(int i=lim;i<k;i++) { zc=(o*10%m+i)%m; if(!ex[zc]||zc==0) { nxt[++e]=fir[o]; fir[zc]=e; to[e]=i; ex[zc]=1; q[++t]=zc; } if(zc==0) return; } } } int main() { int w=0; k=read();m=read(); solve(); for(int i=fir[0];i;i=nxt[i]) out[++w]=to[i]; for(int i=w;i>=1;i--) putchar(out[i]+'0'); return 0; }