poj1426

快2个月没接触算法了,今天开始每天坚持算法学习,坚持刷题


涉及算法:广度搜索+同余模定理

题目大意:给定一个正整数n(1<=n<=200)求出任意一个n的倍数m,要求m只能由0、1表示。

题目分析:

bfs的过程如下:
1 mod n
10 mod n   11 mod n
100 mod n   101 mod n    110 mod n   111 mod n
.........

这样下去会出现大数,为了避免大数的出现,我们运用了下面的方法,

同余公式:
(a+b)%  n = (a%n+b)%n=(a+b%n)%n=(a%b+b%n)% n
(a*b)%  n = (a%n*b)%n=(a*b%n)%n=(a%n*b%n)% n

如果我们现在有一个数k,要看是否是n的倍数,由于k只能由0或1组成,则k=(k/10)*10+1(若k为基数)或k=(k/10)*10(若k为偶数),所以可以得到:k=(k/10)*10+k%2,k%n=((k/10)*10+k%2)%n=(((k/10)%n*10)%n+k%2)%n=((k/10)%n*10+k%2)%n,这样(k/10)%n的值永远不会大于n,,解决了大数问题。我们用mod[i]表示i对n求余的结果,求mod[i]时,显然要用到mod[i/10],这下问题又来了,数组的下标i/10会很大,我们需要开一个很大的数组,这显然是不现实的,为了解决这个问题,我们可以用10进制数来表示2进制,例如,用2来表示10、16来表示10000、33来表示100001,,这样数组就不用开到很大,若我们要求mod[33]只需要知道mod[16]即可,可以推出公式mod[i]=(mod[i/2]*10+i%2)%n,当mod[i]=0时,说明找到了合适的i,输出i的二进制形式就可以了

代码如下:

import java.util.Scanner;

public class Main_1426 {

	static int a;
	static int[] mod=new int[524287];
	public static void main(String[] args) {
		Scanner in=new Scanner(System.in);
		a=in.nextInt();
		while(a!=0){
			bfs();
			a=in.nextInt();
		}
	}
	
	static void bfs(){
		mod[1]=1;
		int i=0;
		for(i=2;mod[i-1]!=0;i++){
			mod[i]=(mod[i/2]*10+i%2)%a;
		}
		i--;
		int tmp=0;
		while(i>0){
			mod[tmp++]=i%2;
			i/=2;
		}
		for(i=0;i<tmp;i++){
			System.out.print(mod[tmp-i-1]);
		}
		System.out.println();
	}
}




你可能感兴趣的:(poj)