题目描述
q=(√5+1)/2,在黄金系统下面a0a1…an等于 ∑ni=0ai∗qn−i ,其中 ai 是0或者1。
现在给出两个黄金系统下面的数字a和b,请比较他们的大小。
n<=10^5
类斐波那契数
q2=(√5+1)2/4=(5+1+2√5)/4=(3+√5)/2=1+(1+√5)/2=1+q
所以n>=2时有qn=qn−2∗q2=qn−2(q+1)=qn−1+qn−2
根据这个,我们可以设f[i]表示qi的系数,初识时,若ai=1则f[n-i]++;若bi=1则f[n-i]–。f[i]的值可以转移到f[i-1]和f[i-2],所以最后我们可以全部转移到f[1]和f[0],就可以比较a和b的大小了(f[1]*q+f[0]>0则a>b)。
直接这样就能过了吗?too naive。
f的值显然可以爆long long。
f是从高位往低位转移的,事实上,在这个过程中当某个f[i]的值的绝对值大于2(也就是高位上第一个f的值的绝对值大于1)且i>2时,a和b大小就已经能够确定了。
假设f[i]=2,因为f[i+1]的绝对值小于等于1,所以f[i-1]的值最小为-1-1=-2,那么f[i]的值转移给f[i-1]和f[i-2]后,f[i-1]>=0,姑且先当f[i-1]=0,而f[i-2]的值最小为-1+2=1,也先当f[i-2]=2(这样保证a是最小的),f[i-2]对后面所有的转态都至少造成了+1的影响,而后面的f>=-1,所以至少有a>=b,而当i>2时,显然可以保证a>b。
代码
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<cmath>
#define fo(i,a,b) for(i=a;i<=b;i++)
#define fod(i,a,b) for(i=a;i>=b;i--)
#define ll long long
using namespace std;
const int maxn=100000+5;const double p=(sqrt(5)+1)/2;
int f[maxn],l1,l2,i;
char a[maxn],b[maxn];
int main(){
scanf("%s",a+1);
scanf("%s",b+1);
l1=strlen(a+1),l2=strlen(b+1);
fo(i,1,l1) f[l1-i]=a[i]-'0';
fo(i,1,l2) f[l2-i]+='0'-b[i];
fod(i,max(l1,l2),3){
if (f[i]<-1) {printf("<\n");return 0;}
if (f[i]>1) {printf(">\n");return 0;}
f[i-1]+=f[i],f[i-2]+=f[i];
}
f[1]+=f[2],f[0]+=f[2];
if (f[1]==0&&f[0]==0) {printf("=\n");return 0;}
double s=f[1]*p+f[0];
if (s>0) printf(">\n");else printf("<\n");
}