Regionals 2011 >> Asia - Shanghai 5711 - Revenge of Fibonacci

点击打开链接

给定一个长度不超过40的数字串s,求斐波那契数列的前十万项中,最小的一个前缀为s的数的下标。

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.math.BigInteger;
import java.util.Arrays;
import java.util.StringTokenizer;

public class Main {
	public static void main(String[] args) {
		new Task().solve();
	}
}

class Task {
	InputReader in = new InputReader(System.in) ;
	PrintWriter out = new PrintWriter(System.out) ;
	final int N = 50 ; 
	Tire tire = new Tire() ; 
	void solve() {
		tire.clear() ; 
		int[][] fib = new int[3][N] ;
		Arrays.fill(fib[0] , 0) ;
		Arrays.fill(fib[1] , 0) ;
		Arrays.fill(fib[2] , 0) ;
	
		fib[0][0] = 1 ;
		fib[1][0] = 1 ;
		tire.add(fib[0] , 0) ;
	  
		for(int n = 2 ; n < 100000 ; n++){
			int i = 0  , c = 0 ;
			for( ; i < N ; i++){
				fib[2][i] = (c + fib[1][i] + fib[0][i]) % 10 ;
				c = (c + fib[1][i] + fib[0][i]) / 10 ;
			}
			if(i == N && c > 0){
				for(int k = 0 ; k <= N-2 ; k++){
					fib[2][k] = fib[2][k+1] ;
					fib[1][k] = fib[1][k+1] ;
				}
				fib[2][N-1] = c ;
				fib[1][N-1] = 0 ;
			}
			for(int k = 0 ; k < N ; k++){
				fib[0][k] = fib[1][k] ;
				fib[1][k] = fib[2][k] ;
			}
			tire.add(fib[2] , n) ;
		}
		
	    int t = in.nextInt() ;
	    for(int cas = 1 ; cas <= t ; cas++){
	    	out.println("Case #" + cas  + ": " + tire.find(in.next().toCharArray())) ;
	    }
		out.flush() ;
	}
}


class Tire{
	final int nodeSize = 100000*40 + 8 ;
	final int sonSize = 10 ;
	int[][] next = new int[nodeSize][sonSize] ;
	int[] lable = new int[nodeSize] ;
	int root , totel ;
	
	int newNode(){
		for(int i = 0 ; i < sonSize ; i++){
			next[totel][i] = 0 ;
		}
		lable[totel] = -1 ;
		return totel++ ;
	}
	
	void clear(){
		totel = 0 ;
		root = newNode() ;
	}
	
	void add(int[] word , int id){
		int now = root ;
		int i = word.length - 1 , len = 0  ;
		while(i >= 0 && word[i] == 0){
			i-- ;
		}
		while(i >= 0 && ++len <= 40){
			if(next[now][word[i]] == 0){
				next[now][word[i]] = newNode() ;
			}
			now = next[now][word[i]] ;
			if(lable[now] == -1){
				lable[now] = id ;
			}
			i-- ;
		}
	}
	
	int find(char[] word){
		int now = root ;
		for(char c : word){
			int i = c - '0' ;
			if(next[now][i] == 0){
				return -1  ;
			}
			now = next[now][i] ;
		}
		return lable[now] ; 
	}
	
}


class InputReader {
	public BufferedReader reader;
	public StringTokenizer tokenizer;

	public InputReader(InputStream stream) {
		reader = new BufferedReader(new InputStreamReader(stream), 32768);
		tokenizer = new StringTokenizer("");
	}

	private void eat(String s) {
		tokenizer = new StringTokenizer(s);
	}

	public String nextLine() {
		try {
			return reader.readLine();
		} catch (Exception e) {
			return null;
		}
	}

	public boolean hasNext() {
		while (!tokenizer.hasMoreTokens()) {
			String s = nextLine();
			if (s == null)
				return false;
			eat(s);
		}
		return true;
	}

	public String next() {
		hasNext();
		return tokenizer.nextToken();
	}

	public int nextInt() {
		return Integer.parseInt(next());
	}

	public long nextLong() {
		return Long.parseLong(next());
	}

	public double nextDouble() {
		return Double.parseDouble(next());
	}

	public BigInteger nextBigInteger() {
		return new BigInteger(next());
	}

}



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值