Chapter05-Multiple(POJ 1465)

Multiple

Time Limit: 1000MS

Memory Limit: 32768K

Total Submissions: 5911

Accepted: 1284

Description

a program that, given anatural number N between 0 and 4999 (inclusively), and M distinct decimaldigits X1,X2..XM (at least one), finds the smallest strictly positive multipleof N that has no other digits besides X1,X2..XM (if such a multiple exists).

Input

The input has several datasets separated by an empty line, each data set having the following format:

On the first line - the number N
On the second line - the number M
On the following M lines - the digits X1,X2..XM.

Output

For each data set, the programshould write to standard output on a single line the multiple, if such amultiple exists, and 0 otherwise.

An example of input and output:

Sample Input

22

3

7

0

1

 

2

1

1


Sample Output

110
0

Source

SoutheasternEurope 2000

 

题目大意:

       给定一个数N(0<=N<=4999),现在给定若干个十进制的数,能否用给定的十进制的数组成一个数,使其是N的倍数,如果存在,请求出倍数最小的数,如果不存在,请输出0;

       十进制的数可以无限次重复使用,例如N=22;用7,0,1三个十进制的数可以组成110使其是22的最小的倍数;

 

该题必须解决两个问题:

1, 怎么判断不存在该数的倍数,也就是说在什么情况下可以停止遍历;

2, 因为数的可能大小非常大,我们不能用int来存储,那么需要怎么解决这个问题;

3, 如何保证取出的数是最小的额

 

取余数操作,从个位数开始,对每个数取余,若余数不为零,那么对每个余数添加增加所有的可能性,依次无线循环;何时结束呢?就是取余的时候,如果发现该余数已经是第二次出现了,那么可以丢弃,因此也就是说,最多需要遍历4999次,把所有的余数都取了一遍;

存数,我们可以用数组来存储每一位数,不妨新建一个类,每一种组合新建一个类;类包含成员prev,指向上一个数,打个比方,首次遍历 分别为数1,7新建一个类,他们的prev指向空,数1又能衍生出3个类,数1,0,7,此时他们的prev分别指向数1;同时也要有成员modNum保存当前的余数,也要有一个成员currentNum表示当前的数是多少。

为了保证取出的数是最小的,我们给这些十进制的数排序,每次取数从小开始取数,因为是fifo队列,所以总是从最小的计算;

 

开始动手写代码吧。。。

Java代码如下:

import java.io.BufferedInputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.Scanner;

public class Main {
	// 用来标记所有的余数,比如余数32,可以表示allModNum[32]=1;表示已经存在
	private int[] allModNum;

	// 这是存放十进制数的数组;
	private int[] number;
	private int N;

	public Main(int N) {
		this.N = N;
		if (N != 0) {
			allModNum = new int[N];
			Arrays.fill(allModNum, 0);
		}
	}

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner cin = new Scanner(new BufferedInputStream(System.in));
		
		int N ;
		while (cin.hasNext()) {
			N = cin.nextInt();
			Main ma = new Main(N);
			int countNum;
			countNum = cin.nextInt();
			ma.number = new int[countNum];

			for (int i = 0; i < countNum; i++) {
				ma.number[i] = cin.nextInt();
			}
			
			
			ma.processItBfsAndPrint();
			
			
		}
	}

	private void processItBfsAndPrint() {
		// TODO Auto-generated method stub

		// 辅助实现的队列;
		LinkedList<Node> al = new LinkedList<Node>();

		Arrays.sort(number);
		

		// 这个事特例哈;
		if (N == 0) {
			System.out.println(0);
			return;
		}
		
		Arrays.fill(allModNum, 0);
		
		if (number[0] != 0) {
			if (number[0] % N == 0) {
				System.out.println(number[0]);
				return;
			}
			al.add(new Node(null, number[0] % N, number[0]));
			allModNum[number[0] % N] = 1;
		}

		for (int i = 1; i < number.length; i++) {

			if (number[i] % N == 0) {
				System.out.println(number[i]);
				return;
			}

			al.add(new Node(null, number[i] % N, number[i]));
			allModNum[number[i] % N] = 1;
		}

		Node nodetemp;

		int modTemp;

		while (al.size() > 0) {
			nodetemp = al.remove();
			for (int i = 0; i < number.length; i++) {

				modTemp = (nodetemp.modNum * 10 + number[i]) % N;

				// 这就是我们需要的值;
				if (modTemp == 0) {
					// 用来暂时保存所有的值
					ArrayList<Integer> ans = new ArrayList<Integer>();
					ans.add(number[i]);
					while (nodetemp != null) {
						ans.add(nodetemp.currentNum);
						nodetemp = nodetemp.prev;
					}

					for (int j = ans.size() - 1; j >= 0; j--) {
						System.out.print(ans.get(j));
					}
					System.out.println();
					return;
				}

				if (allModNum[modTemp] == 0) {
					allModNum[modTemp] = 1;
					al.add(new Node(nodetemp, modTemp, number[i]));
				}
			}
		}

		System.out.println(0);
	}

	static class Node {
		private Node prev;
		private int modNum;
		private int currentNum;

		public Node(Node prev, int modNum, int currentNum) {
			this.prev = prev;
			this.modNum = modNum;
			this.currentNum = currentNum;
		}
	}

}





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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值