51nod 1109 01组成的N的倍数

来源:互联网 发布:java打包jar工具 编辑:程序博客网 时间:2024/06/05 15:38

1109 01组成的N的倍数
基准时间限制:1 秒 空间限制:131072 KB 分值: 40 难度:4级算法题
给定一个自然数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

解题思路:运用队列存储余数,逐一判断,知道满足条件,每次在M后面添加一位数a(题目要求其中a为0或者为1),使M扩大为10*M+a

即:原数为M,扩大后的数为M1=10*M+a

        将其对mod取模,则:mod_M=M%mod    mod_M1=(10*M+a)%mod = (10*M%mod + a%mod)%mod =  (10*M%mod+a)%mod = (10*mod_M+a)%mod

        由此我们可以知道,当M满足条件时,则:mod_M1=0

       可以将其假设成为一个带权值的图,其权值为数字0或者1,其顶点值为余数,最后可以看成从起点到第一个顶点为0的路径就是最后结果;

       在余数入队的时候要判断是否在之前就出现过,如果出现过,则不入队,因为如果出现重复的,那么就会出现无限循环,这样永远也得不到余数为0 的这个条件,所以直接舍去,如果没有出现过,则将其入队,并且用b数组将其标记,a数组用来保存权值,其中两者都以余数作为下标;则b数组保存路径,a数组保存权值,最后根据路径输出所以权值。

         

代码如下:

#include <bits/stdc++.h>using namespace std;const int maxn = 1e6+10;int a[maxn],b[maxn];void print(int s)///输出函数{    if(s==-1) return ;    print(b[s]);    printf("%d",a[s]);}int main(){    int n,f=0,s;    scanf("%d",&n);    if(n==1) {printf("1\n"); return 0;}///1作为特判    queue<int>Q;    Q.push(1);    b[1] = -1;    a[1] = 1;    while(!Q.empty())    {        s=Q.front();        Q.pop();        int c1=10*s%n,c2=(10*s+1)%n;        if(c1 == 0) {f=0; break;}        if(c2 == 0) {f=1; break;}        if(!b[c1]){Q.push(c1); a[c1] = 0; b[c1]=s;}///判断是否出现循环        if(!b[c2]){Q.push(c2); a[c2] = 1; b[c2]=s;}    }    print(s);    printf("%d\n",f);    return 0;}