[hdu 4814]Golden Radio Base 找规律

该题为2013ICPC亚洲区预选赛长春站B题
http://acm.hdu.edu.cn/showproblem.php?pid=4814

题意很简单:给定一个十进制数,要求输出在(1+sqrt(5))/2进制中的数的表示。


这题做模拟赛的时候拿到有点摸不着头脑,第一直觉是想用java大数来做,但是后来发现样例中的每个结果计算出来都是整数,卡精度的方法其实是不可取的。

后来又因为发现1+1=10.01想到九进制转二进制,但是发现转换要写高精度,不好实现...

当时这题也就放下了。后来再看到这题才发现原来条件都在题目中清晰给出了。即:


1.相同位数相加 1+1=10.01

2.不同位数出现连续两个1 即11=100


直接看作是二进制的两种特殊运算来对待即可


由于二者互相独立

则类似3+2=20.02+1 

而进一步对于20.02中的每一个2也进行处理,对于连续的两个1产生进位之后加上的1可能会出现新的2的情况,采用标记进行循环处理,直至无需处理符合要求。


一些处理:

为了防止处理前导0以及结尾0和小数点,直接define了小数点所在的位置,采用string输出

数组开太大会TLE 预先要估算数字大约会在100位(小数点前后各50位)


700ms,应该优化的空间还是有

code:

#include  <iostream>
#include <cstdio>
#include <algorithm>
#include <string>
#include <cstring>
#include <cstdlib>
#define INF 0x3f3f3f3f
#define dem 50

using namespace std;
int i,p,l,j,n,m,head,tail;
int base[33][105];
int ans[105];
string si;
int main()
{
	memset(base,0,sizeof(base));
	base[0][dem]=1;
	for (i=1;i<=32;i++)
		{
		for (j=1;j<=100;j++)
		base[i][j]=base[i-1][j]*2;
		do{
			do{
				p=0;
				for (j=1;j<=100;j++)
				if (base[i][j]>1) {
					p=1;
					base[i][j-1]+=base[i][j]/2;
					base[i][j+2]+=base[i][j]/2;
					base[i][j]=base[i][j]%2;}
			}
			while (p);
			p=0;
			for (j=100;j;j--)
				if (base[i][j+1]==1&&base[i][j+2]==1)
				{
					p=1;
					base[i][j+1]=base[i][j+2]=0;
					base[i][j]+=1;
				}
			}
		while(p);
		}
	while(scanf("%d",&n)!=EOF)
	{
		memset(ans,0,sizeof(ans));
		m=n;
		l=0;
		while(m)
		{
			if (m%2)
			{
				for (j=1;j<=100;j++)
				ans[j]+=base[l][j];
				do{
					do{
						p=0;
						for (j=1;j<=100;j++)
						if (ans[j]>1) 
							{
							p=1;
							ans[j-1]+=ans[j]/2;
							ans[j+2]+=ans[j]/2;
							ans[j]%=2;
							}
						}
					while (p);
					p=0;
					for (j=100;j;j--)
						if (ans[j+1]==1&&ans[j+2]==1)
						{
						p=1;
						ans[j+1]=ans[j+2]=0;
						ans[j]+=1;
						}
					}
				while(p);
			}
		m/=2;
		l++;
		}
		for (i=0;i<=100;i++)
			if (ans[i]) break;
			head=i;
		for (i=0;i<=100;i++)
			if (ans[i]) tail=i;
		for (i=head;i<=tail;i++)
		{
			printf("%d",ans[i]);
			if (i==dem&&tail>dem) printf(".");
		}
		printf("\n");
		}
	return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值