JZOJ 3769.【NOI2015模擬8.14】A+B

DescriptionDescription

定義斐波那契表示序列是用形如y=i=1FbiAiy=\sum_{i=1}^{\infty}Fb_iA_i表示yy的序列AA

給定兩個長度爲n,mn,m的斐波那契最大表示序列,求它們和的斐波那契最大表示序列

定義更大的斐波那契序列是在長度更大的基礎上,字典序儘量大

數據範圍:n106n\leq 10^6


SolutionSolution

首先兩個表示序列先相加,然後重複以下操作直到序列中只有0或1(易證這樣的情況下是最優的)

對於相鄰的1,不斷做合併

對於各種的2,前後發散

由於在最壞條件下算法會跌落成O(n2)O(n^2),但是似乎也沒有什麼更好的解法了

於是就O()O(玄學)過掉了


CodeCode

#include<cctype>
#include<cstdio>
#include<algorithm> 
#define LL long long
#define N 1000100
using namespace std;int n,m,a[N],l,b[N],t;
bool flag=1;
inline LL read()
{
	char c;LL d=1,f=0;
	while(c=getchar(),!isdigit(c)) if(c=='-') d=-1;f=(f<<3)+(f<<1)+c-48;
	while(c=getchar(),isdigit(c)) f=(f<<3)+(f<<1)+c-48;
	return d*f;
}
signed main()
{
	n=read();for(register int i=1;i<=n;i++) a[i]=read();
	m=read();for(register int i=1;i<=m;i++) b[i]=read();
	l=max(n,m)+30;
	if(a[1]) b[!b[1]]=1;a[1]=0;
	for(register int i=1;i<=l;i++) b[i]+=a[i];
	while(flag)
	{
		for(register int i=1;i<=l;i++) if(b[i]&&b[i-1]) t=min(b[i],b[i-1]),b[i+1]+=t,b[i-1]-=t,b[i]-=t;
		flag=false;
		for(register int i=++l;i>0;i--) if(b[i]>1) {b[i+1]++;b[i]-=2;if(i>1) b[i-2]++;flag=true;}
	}
	while(b[l]==0) l--;
	printf("%d ",l);b[1]+=b[0];
	for(register int i=1;i<=l;i++) printf("%d ",b[i]);
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章