#斐波那契# [jzoj 3769] 【NOI2015模拟8.14】A+B

题目

Description
对于每个数字x,我们总可以把它表示成一些斐波拉切数字之和,比如8 = 5 + 3, 而22 = 21 + 1,因此我们可以写成 x = a1 * Fib1 + a2 * Fib2 + a3 * Fib3 + … + an * Fibn, 其中,Fib1 = 1, Fib2 = 2…. Fib[i] = Fib[i – 1] + Fib[I - 2], 且a[n] > 0.那么我们称ai为x的一种斐波拉切表示,由于表示方法有很多种,我们要求最大化a[1…n],即,如果b[1…n]和a[1…m]都可以表示x,若m > n 则a更大,若 m = n, 则从高位到低位比,第一个不同处i,若ai > bi 则a比b大。

你的任务很简单,给你两个用斐波拉切数最大化表示的两个数字,输出他们相加后用斐波那契最大化表示的数字。


解题思路


代码

#include
#include
#include
#define rr register 
using namespace std;
const int N=2e6+10; 
int len,len1,a[N]; 
inline int read(){
	rr int p=0; rr char c=getchar(); 
	while (!isdigit(c)) c=getchar(); 
	while (isdigit(c)) p=(p<<3)+(p<<1)+c-48,c=getchar(); 
	return p; 
}
inline void askans(){
	len1=a[1],a[1]=0,++a[len1]; 
	if (a[2]==2) {
		++a[1],a[2]-=2,++a[3]; 
		if (len<3) len=3; 
	}
	for (rr int i=3;i<=len;i++) if (a[i]>=2){
		++a[i+1],++a[i-2],a[i]-=2; 
		if (i+1>len) len=i+1; 
	}
	if (len1>len) len=len1; 
	for(rr int i=1;i<=len;i++)
		while (a[i]&&a[i+1]){
			++a[i+2],--a[i],--a[i+1]; 
			if (i+2>len) len=i+2; 
		}
}
inline bool check(){
	for(rr int i=1;i<=len;i++) if (a[i]>1) return 1; 
	return 0; 
}
signed main(){
	len1=read(); 
	for(rr int i=1;i<=len1;i++) a[i]=read(); 
	len=read(); 
    for (rr int i=1;i<=len;++i) a[i]+=read(); 
    len=len>len1?len:len1; 
	do{askans();}while(check()); 
	printf("%d",len); 
	for(rr int i=1;i<=len;++i) printf(" %d",a[i]); 
	return 0; 
}
	  	

你可能感兴趣的:(深度优先搜索(dfs))