hdu4814 Golden Radio Base

2013年长春现场赛的B题。当时没有仔细看题目提示上的式子,非常遗憾地错过了这道其实比较水的题。

题目大意是输入一个十进制数,要求输出用φ进制表示的该数,φ是黄金比例数1.61803399......。

样例输入输出里给的是:

Sample Input
1
2
3
6
10
Sample Output
1
10.01
100.01
1010.0001
10100.0101

题目hint里给了两个式子:“φ + 1 = φ ^ 2” 和 “2 * φ ^ 2 = φ ^ 3 + 1”

如果将两式左右都乘上φ ^ n-2,就得到 “φ ^ (n - 1) + φ ^ (n - 2) = φ ^ n” 和 “2 * φ ^ n = φ ^ (n  + 1) + φ ^ (n  - 2)”


第一个式子可以表示φ进制数在任意两位上遇到连续的1,即11,都可以转化为100。

例如样例里2的φ进制表示为10.01,那么3就是11.01,题目要求输出里不能有连续的1,所以根据以上法则转化为100.01。


第二个式子可以表示φ进制数在任意一位上的2,都可以转化为1001。

例如4的φ进制表示为101.01,5就可以表示为102.01,根据那两个式子转化之后得1000.1001。

依此类推得6的φ进制表示为1001.101,转化得到1010.001


当然,题目给的数据范围是10^9,不能直接从1开始一个一个推着算,所以只要根据数据范围将2^0到2^29的φ进制表示算出来就行了。

拿6举例:6=4+2

2的φ进制表示:10.01

4的φ进制表示:101.01

那么6就是 10.01 + 101.01 = 111.02

111.02 -> 1001.02 -> 1001.1001 -> 1010.0001


现场的时候一方面没有仔细理解题意,也没有仔细思考提示中的那两个式子该怎么用,以为还要用到浮点运算,其实只要理清思路就是单纯的模拟了。


下面附上我的源码:


#include <cstdio>
#include <cstring>
#define LEN 100
#define HLE 50
using namespace std;

typedef struct fbn {
    int a[LEN];
    int pn;
    void init() {
        memset(a, 0, sizeof(a));
        pn = 0;
    }
    void print() {
        bool b = false;
        for (int i = 0; i < HLE; i++) {
            if (a[i] != 0) b = true;
            if (b == true) printf("%d", a[i]);
        }
        if (pn != 0) {
            printf(".");
            for (int i = 0; i < pn; i++)
                printf("%d", a[i + HLE]);
        }
        printf("\n");
    }
}FBN;

bool check(FBN a)
{
    bool t = true;
    for (int i = 0; i < LEN; i++) {
        if (a.a[i] > 1) {t = false; break;}
        if ((i != LEN - 1) && a.a[i] == 1 && a.a[i + 1] == 1) {t = false; break;}
    }
    return t;
}

FBN normalize(FBN a)
{
    int t;
    do {
        for (int i = 0; i < LEN; i++) {
            if (a.a[i] > 1) {
                t = a.a[i] / 2;
                a.a[i] %= 2;
                a.a[i - 1] += 1;
                a.a[i + 2] += 1;
            }
            if ((i != LEN - 1) && a.a[i] == 1 && a.a[i + 1] == 1) {
                a.a[i - 1] += 1;
                a.a[i] = 0;
                a.a[i + 1] = 0;
            }
        }
    } while (!check(a));
    for (int i = LEN - 1; i >= HLE; i--) {
        if (a.a[i] != 0) {
            a.pn = i - HLE + 1;
            break;
        }
    }
    return a;
}

FBN add(FBN a, FBN b)
{
    FBN ans;
    ans.init();
    for (int i = 0; i < LEN; i++) {
        ans.a[i] = a.a[i] + b.a[i];
    }
    ans = normalize(ans);
    return ans;
}

int main()
{
    int n, i;
    FBN twob[30], ans;
    for (i = 0; i < 30; i++) twob[i].init();
    twob[0].a[HLE - 1] = 1;
    twob[0].pn = 0;
    for (i = 1; i < 30; i++) {
        twob[i] = add(twob[i - 1], twob[i - 1]);
    }
    while (scanf("%d", &n) != EOF) {
        i = 0;
        ans.init();
        while (n > 0) {
            if ((n & 1) == 1) ans = add(ans, twob[i]);
            n >>= 1;
            i++;
        }
        ans.print();
    }
    return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值