POJ 1465 Multiple(用BFS求能组成的n的最小倍数)

题目地址:点击打开链接

题意:给一个数n,接着给m个数,用给已知的m个数组成的数最小的能被n整除的数是多少(其中m个数可以重复使用)

思路:和HDU1226有点相似,只不过比那道题简单,这里面m的数值没有说明,但是可以猜出来,问题的解空间是m^m,所以开一个大小为50的数组足够了,组成的数可以很大,必须不断取模,而且解空间太大,必须用同余减枝,而且必须减枝,否则第二个测试案例就出错误,因为程序会陷入死循环,假设A%N==B%N(设A<B),那么只取前面的数即可,因为前面的数小。本质就是求l%n==0,问最小的l是多少,假设组成l的数为A和B,则求(A%N+B)%N ==0,注意B不能对n取余,看代码注释掉的部分,会造成RE,没搞明白为啥,只搞明白有一种情况会出错,如m个数中有一个数和n相同,提前对m个数组取模会造成错误

AC代码:

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <queue>
#include <stack>
#include <map>
#include <cstring>
#include <climits>
#include <cmath>
#include <cctype>

typedef long long ll;
using namespace std;

int a[50];
int n,m;
int visit[5000];

struct node
{
    int now;
    int pre;
    int id;
    int wei;
}cf[5000],lol;

void shuchu(int id)
{
    if(cf[id].pre == -1)
    {
        return;
    }
    shuchu(cf[id].pre);
    printf("%d",cf[id].wei);
}

void bfs()
{
    int i,k=0;
    queue<node> que;
    cf[k].now = 0;
    cf[k].pre = -1;
    cf[k].id = k;
    que.push(cf[k]);
    while(!que.empty())
    {
        lol = que.front();
        que.pop();
        for(i=0; i<m; i++)
        {
            if(!visit[(lol.now*10+a[i])%n] && (lol.id != 0 || a[i] > 0))//与后面的语句必须加因为第一个数不可能为0
            {
                k++;
                cf[k].now = (lol.now*10+a[i])%n;
                cf[k].pre = lol.id;
                cf[k].wei = a[i];
                cf[k].id = k;
                visit[cf[k].now] = 1;
                if(cf[k].now == 0)
                {
                    shuchu(k);
                    printf("\n");
                    return;
                }
                que.push(cf[k]);
            }
        }
    }
    printf("0\n");
}

int main()
{
    int i;
    while(scanf("%d%d",&n,&m) != EOF)
    {
        memset(visit,0,sizeof(visit));
        for(i=0; i<m; i++)
        {
            scanf("%d",&a[i]);
            //a[i] = a[i] % n;
        }
        sort(a,a+m);
        if(n == 0)
        {
            printf("0\n");//这里包含2种情况,n为0是最小倍数一定为0 ,a数组中没0时,没法组成0的最小倍数时,输出的也是0
        }
        else
        {
            bfs();
        }
    }
    return 0;
}

大神地址:点击打开链接


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值