HDU1664 (bfs +数论剪枝)

Different Digits

Time Limit: 10000/4000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)

Total Submission(s): 1129 Accepted Submission(s): 290

Problem Description

Given a positive integer n, your task is to find a positive integer m, which is a multiple of n, and that m contains the least number of different digits when represented in decimal. For example, number 1334 contains three different digits 1, 3 and 4.

Input

The input consists of no more than 50 test cases. Each test case has only one line, which contains a positive integer n ( 1<=n < 65536). There are no blank lines between cases. A line with a single `0’ terminates the input.

Output

For each test case, you should output one line, which contains m. If there are several possible results, you should output the smallest one. Do not output blank lines between cases.

Sample Input

7

15

16

101

0

Sample Output

7

555

16

1111

Source

2004 Asia Regional Shanghai

Recommend

xhd | We have carefully selected several similar problems for you: 1667 1668 1666 1661 1662

感觉是ZOJ1136 的高级版http://blog.csdn.net/u013167299/article/details/47170483


#include<bits/stdc++.h>
#define cl(a,b) memset(a,b,sizeof(a));
#define LL long long
#define out(x) cout<<x<<endl;
using namespace std;
const int maxn=65540;
const int inf=9999999;
int n;
int a[2];
int used[maxn];
struct node{
    int pre,d,mod,id;//pre是该节点的前驱节点,d是当前加在末尾的数,mod是到目前为止组合的数对n的余数,id是编号,便于查找,
    node(){}
    node(int a,int b,int c,int tt){
        pre=a;d=b;mod=c;id=tt;
    }

}q[maxn];//直接模拟队列,便于记录路径
string ans,tmpans;

bool bfs(int m){
    int sum=0;
    int st=0,en=0;
    cl(used,0);
    for(int i=0;i<m;i++){
        q[en++]=node(-1,a[i],a[i]%n,sum++);
        if(a[i])used[a[i]%n]=1;
    }
    int len=0;
    while(st<en){
        node s=q[st++];
        if(s.mod==0&&(s.id>0||s.id==0&&s.d!=0)){
            tmpans="";
            tmpans+=char(s.d+‘0‘);
            int t=s.pre;
            while(t!=-1){//路径转化成字符串
                tmpans+=q[t].d+‘0‘;
                t=q[t].pre;
            }
            reverse(tmpans.begin(),tmpans.end());
            //out(tmpans)
            return true;
        }
        for(int i=0;i<m;i++){
            node tmp=s;
            if(len==0&&tmp.d==0&&tmp.mod==0)continue;
            if(used[(tmp.mod*10+a[i])%n]++)continue;
            len++;
            q[en++]=node(s.id,a[i],(s.mod*10+a[i])%n,sum++);
        }
    }
    return false;
}

int main(){
    while(~scanf("%d",&n)&&n){
        ans="zcc";
        for(int i=1;i<10;i++){
            a[0]=i;
            if(bfs(1)){
                if(ans=="zcc")ans=tmpans;
                else if(tmpans.size()<ans.size()){
                    ans=tmpans;
                }
                else if(ans.size()==tmpans.size()){
                    ans=min(ans,tmpans);
                }
            }
        }
        if(ans=="zcc")for(int i=0;i<10;i++){
            a[0]=i;
            for(int j=i+1;j<10;j++){
                a[1]=j;
                if(bfs(2)&&tmpans!="0"){
                    if(ans=="zcc")ans=tmpans;
                    else if(tmpans.size()<ans.size()){
                        ans=tmpans;
                    }
                    else if(ans.size()==tmpans.size()){
                        ans=min(ans,tmpans);
                    }
                }
            }
        }
        out(ans)
    }
    return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-11 00:21:25

HDU1664 (bfs +数论剪枝)的相关文章

HDU1664 BFS + 数论 + 剪枝

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1664 , 一道比较蛋疼的搜索题. 这道题有很多坑点,一点处理不好就要TLE. 题意很简单,就是找到一个n的倍数m,要求m里包含的不同数字最少. 做这道题要有数论的知识:对于任意的整数n,必然存在一个由不多于两个的数来组成的一个倍数. 所以这里就比较好入手了,就是先搜一个数的情况,没找到的话再搜两个数的情况. 具体解法: 用BFS来搜索,注意要有两个剪枝:如果当前队列里的结点的字符串的长度要比已经得到

ZOJ 1136 Multiple(BFS + 数论 同余剪枝 搜索数字的倍数 )

ZOJ Problem Set - 1136 Multiple Time Limit: 10 Seconds Memory Limit: 32768 KB 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 smallest strictly positive mult

hdu 1044(bfs+dfs+剪枝)

Collect More Jewels Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 6739    Accepted Submission(s): 1564 Problem Description It is written in the Book of The Lady: After the Creation, the cruel

HDU 4474(神奇的BFS+强剪枝)

 HDU - 4474 Yet Another Multiple Problem Time Limit: 20000MS   Memory Limit: 65536KB   64bit IO Format: %I64d & %I64u Description There are tons of problems about integer multiples. Despite the fact that the topic is not original, the content is hi

UVA - 11882 Biggest Number(dfs+bfs+强剪枝)

题目大意:给出一个方格矩阵,矩阵中有数字0~9,任选一个格子为起点,将走过的数字连起来构成一个数,找出最大的那个数,每个格子只能走一次. 题目分析:DFS.剪枝方案:在当前的处境下,找出所有还能到达的点的个数,若当前数字的长度加上个数仍小于目前最优答案的长度,则剪去:若长度相等,则将所有还能到达的数字按从大到小排序后连到当前数字上,如果还比目前最优解小,则减去.找出所有还能到达的点的过程用BFS实现. 1 #pragma comment(linker, "/STACK:1024000000,10

hdu6223 Infinite Fraction Path 2017沈阳区域赛G题 bfs加剪枝(好题)

题目传送门 题目大意:给出n座城市,每个城市都有一个0到9的val,城市的编号是从0到n-1,从i位置出发,只能走到(i*i+1)%n这个位置,从任意起点开始,每走一步都会得到一个数字,走n-1步,会得到一个长度为n的数列,输出能得到的最大的数列(当成数字). 思路: 一个数字肯定是最高位越大,这个数字本身就越大,所以肯定第一位要取最大值,在这一位取最大值的时候后面每一位都要尽量最大,所以想到bfs. 但是bfs肯定要剪枝,怎么剪枝呢? 1.按照思路,我要取每一位尽可能大的值,所以某一个状态的某

HDU1067 Gap( BFS+ HASH 剪枝,矩阵用一个数表示)

题意:在4*8 的图中,给你4种类型的牌,每种牌序号1-7,比如42表示第4种牌的第二张,现在给你4*7一共28张,同时最左边的一列开始空的,第一步你要做的是把每种类型的1号牌从上到下放在这列空的位置上,然后在新出现的空位置,你要挑选空位子左边的那张牌的后继,如果没有的话,就不能操作. 解法:题目的状态很多,还有要怎么表示一个状态已经搜索过了呢.那就把矩阵做一下转化,把当前矩阵按行展开,以2为基数化为十进制的数(最大2^32,所以用Long Long),接下来存储这些整数,用map,set应该也

hdu - 1104 Remainder (bfs + 数论)

http://acm.hdu.edu.cn/showproblem.php?pid=1104 注意这里定义的取模运算和计算机的%是不一样的,这里的取模只会得到非负数. 而%可以得到正数和负数. 所以需要 a mod b = (a % b + b) % b 这样转换得到. 并且,由于新的N可以很大,所以我们每一步都要取%,而且最后要mod k,正常来说每步都%k就行了,但是由于其中的一个操作是N%m,所以我们每一步就不能%k了(%k%m混用会导致%出来的答案错误),而要%(k *m)(其实%(k,

Gym - 101572E Emptying the Baltic bfs加剪枝

题目传送门 题目大意:给出一幅海洋的描述,0为海平面,负数即有水,在给出的xy坐标的底部安放抽水机,问最多能有多少水.水往低处流,且八个方向都可以. 思路:bfs,记录到每一个节点有效的最低海平面,然后尝试更新周围的点. 但这道题需要优先队列,有效海平面最低的先出队,否则会TLE. #include<iostream> #include<cstdio> #include<cmath> #include<algorithm> #include<strin