POJ--1465--Multiple【BFS+同余定理】

链接:http://poj.org/problem?id=1465

题意:给一个数字n,和m个数字,找一个由这些数字组成的最小的n的倍数,如果不存在输出0。

思路:这题怎么想都想不到bfs上去,看了别人的解题报告,其实是用bfs来枚举,但是加了一个牛逼的剪枝:同余。即如果A%X==B%X,则(A*10+K)%X==(B*10+K)%X。

我们枚举m中每一个数字做这个K,实际上是枚举了一个数,B*10是之前枚举的数字,如果这个数%X得到的值之前已经得到过,则没必要再往下计算,因为根据同余定理剩下的枚举值和之前的枚举值得到的余数肯定相同,所以没必要再计算。这个剪枝保证了即使一直没找到最小倍数也不至于把数字算到无穷大去,因为n的范围为[0,4999],所以最多只会处理它5000次余数,当余数为0就找到了答案。

为了使得到的答案最小,先对m个数字排序。

细节:n==0时需要特判,X%0会RE出翔。不能用stl的queue,会TLE。

#include<cstring>
#include<string>
#include<fstream>
#include<iostream>
#include<iomanip>
#include<cstdio>
#include<cctype>
#include<algorithm>
#include<queue>
#include<map>
#include<set>
#include<vector>
#include<stack>
#include<ctime>
#include<cstdlib>
#include<functional>
#include<cmath>
using namespace std;
#define PI acos(-1.0)
#define MAXN 500100
#define eps 1e-7
#define INF 0x7FFFFFFF
#define LLINF 0x7FFFFFFFFFFFFFFF
#define seed 131
#define MOD 1000000007
#define ll long long
#define ull unsigned ll
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1

struct node{
    int mod,num,father;
    int id;
}a[20000];
int n,m,cnt,tot;
int flag[5010],b[5010],ans[50010],ff;
void bfs(){
    int i,j;
    int front = 0, rear = 1;
    node t1,t2;
    a[front].mod = 0;
    a[front].num = 0;
    a[front].father = -1;
    while(front<rear){
        t1 = a[front];
        for(i=0;i<m;i++){
            if(!flag[(t1.mod*10+b[i])%n]&&(t1.father!=-1||b[i]!=0)){
                flag[(t1.mod*10+b[i])%n] = 1;
                a[rear].mod = (t1.mod*10+b[i])%n;
                a[rear].num = b[i];
                a[rear].father = front;
                if(a[rear].mod==0){
                    node temp = a[rear];
                    ans[tot++] = b[i];
                    while(1){
                        temp = a[temp.father];
                        if(temp.father==-1) break;
                        ans[tot++] = temp.num;
                    }
                    return ;
                }
                rear++;
            }
        }
        front++;
    }
    ff = 1;
}
int main(){
    int i,j;
    while(scanf("%d",&n)!=EOF){
        ff = tot = cnt = 0;
        memset(flag,0,sizeof(flag));
        scanf("%d",&m);
        for(i=0;i<m;i++){
            scanf("%d",&b[i]);
        }
        sort(b,b+m);
        if(n==0){
            puts("0");
            continue;
        }
        bfs();
        if(ff){
            puts("0");
            continue;
        }
        for(i=tot-1;i>=0;i--){
            printf("%d",ans[i]);
        }
        puts("");
    }
    return 0;
}

POJ--1465--Multiple【BFS+同余定理】,布布扣,bubuko.com

时间: 2024-10-27 12:51:53

POJ--1465--Multiple【BFS+同余定理】的相关文章

poj 1845 Sumdiv (同余定理,快速幂取余)

链接:poj 1845 题意:求A^B的所有因子的和对9901取余后的值 如:2^3=8,8的因子有 1,2,4,8,所有和为15,取余后也是15 应用定理主要有三个: (1)整数的唯一分解定理: 任意正整数都有且只有一种方式写出其素因子的乘积表达式. A=(p1^k1)*(p2^k2)*(p3^k3)*....*(pn^kn)   其中pi均为素数 (2)约数和公式: 对于已经分解的整数A=(p1^k1)*(p2^k2)*(p3^k3)*....*(pn^kn) 有A的所有因子之和为 S = 

Yet Another Multiple Problem 同余定理 bfs

题意: 给出一个n和m个数 求一个最小的数 1 为n的倍数  2 没有这m个数字中的任意一个 123%n = ((((1%n)*10+2)%n)*10+3)%n 如果     a%n==b%n 那么    (a+x)%n==(b+x)%n 这样就可以剪枝了   之前取模n出现过的后来再出现就可以不要了 例如 A%n==B%n 且 A<B 那么B就不用处理了 #include<cstdio> #include<cstring> #include<vector> #i

POJ Multiple (BFS,同余定理)

http://poj.org/problem?id=1465 Multiple Time Limit: 1000MS   Memory Limit: 32768K Total Submissions: 6164   Accepted: 1339 Description a program that, given a natural number N between 0 and 4999 (inclusively), and M distinct decimal digits X1,X2..XM

poj 1465 &amp; zoj 1136 Multiple (BFS+余数重判)

Multiple Time Limit: 1000MS   Memory Limit: 32768K Total Submissions: 6177   Accepted: 1346 Description a program that, given a natural number N between 0 and 4999 (inclusively), and M distinct decimal digits X1,X2..XM (at least one), finds the small

(简单) POJ 1426 Find The Multiple,BFS+同余。

Description Given a positive integer n, write a program to find out a nonzero multiple m of n whose decimal representation contains only the digits 0 and 1. You may assume that n is not greater than 200 and there is a corresponding m containing no mo

poj 2635 The Embarrassed Cryptographer (同余定理,筛选法)

链接:poj 2635 题意:给定一个大数k,k是两个大素数的乘积的值,再给定一个int内的数L 问这两个大素数中最小的一个是否小于L,如果小于则输出这个素数. 分析:因为k达到了10^100,只能用字符串读入,再转化为千进制,用int数组存储, 然后枚举小于L的素数,看是否能被整除,即判断k%L是否为0, 这样就得先用筛选法求素数打表,但是注意要打表到大于10^6 关于高精度取余,就需要用到同余定理 如 123456%N=(((123%N)*1000%N)+456)%N #include<st

POJ 2769 Reduced ID Numbers 同余定理

Reduced ID Numbers Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 8989 Accepted: 3610 Description T. Chur teaches various groups of students at university U. Every U-student has a unique Student Identification Number (SIN). A SIN s is an

[ACM] POJ 2635 The Embarrassed Cryptographer (同余定理,素数打表)

The Embarrassed Cryptographer Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 11978   Accepted: 3194 Description The young and very promising cryptographer Odd Even has implemented the security module of a large system with thousands of

poj1061-青蛙的约会-(贝祖定理+扩展欧几里得定理+同余定理)

青蛙的约会 Time Limit: 1000MS   Memory Limit: 10000K Total Submissions:132162   Accepted: 29199 Description 两只青蛙在网上相识了,它们聊得很开心,于是觉得很有必要见一面.它们很高兴地发现它们住在同一条纬度线上,于是它们约定各自朝西跳,直到碰面为止.可是它们出发之前忘记了一件很重要的事情,既没有问清楚对方的特征,也没有约定见面的具体位置.不过青蛙们都是很乐观的,它们觉得只要一直朝着某个方向跳下去,总能