Sicily 1214. 信号分析

探讨一种来自半人马座的规律性频率信号,通过解析信号中的分隔标志(an=n)来揭示其背后的含义。该文介绍了一个算法,用于计算给定长度L内的信号分隔标志数量。

1214. 信号分析

Constraints

Time Limit: 1 secs, Memory Limit: 32 MB

Description

半人马座(Centaurus)不仅有着美丽的传说,其中的比邻星还是距离太阳系最近的恒星。C博士是一直热衷于对地外文明的探测,最近他发现了一组来自半人马座的奇怪电波信号:1 1 3 1 5 3 7 1……,她怀疑这是来自那里的遥远文明对地球的问候。经过她和助手们的努力,终于发现这是一个很有规律的频率信号a1,a2,a3,……。其中a1=1,a3=3这是信号的开始标志,其余时刻的频率有如下关系:
a2n = an
a4n+1 = 2*a2n+1 - an
a4n+3 = 3*a2n+1 - 2*an
(n>=1)
信号可能很长,其中会有一些分隔标志。C博士在研究中发现这些分隔标志其实是很容易就可以判别出来的,因为它就满足an = n。

为了更进一步发掘这一长串信号的含义,C博士需要知道a1,a2,……,aL中分隔标志有多少个。

Input

只有一个整数L(1<=L<232),表示所要分析信号的长度。

Output

输出一个整数,为这段长L的信号中分隔标志的个数。

Sample Input

8

Sample Output

4

Problem Source

ZSUACM Team Member

// Problem#: 1214
// Submission#: 3586227
// The source code is licensed under Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License
// URI: http://creativecommons.org/licenses/by-nc-sa/3.0/
// All Copyright reserved by Informatic Lab of Sun Yat-sen University
#include <stdio.h>

unsigned long L, sum, e[40], L1;
int b[40], s, i, k;

unsigned long f(unsigned long x) {
    if (x == 1) return 1;
    if (x == 3) return 3;
    if (x % 2 == 0) return f(x / 2);
    if (x % 4 == 1) return 2 * f((x + 1) / 2) - f((x - 1) / 4);
    return 3 * f((x - 1) / 2) - 2 * f((x - 3) / 4);
}

int main() {
    scanf("%lu", &L);
    sum = 0;
    e[0] = 1;
    for (i = 1; i <= 31; i++) e[i] = 2 * e[i - 1];
    s = 0;
    L1 = L;
    while (L1 > 0) {
        s = s + 1;
        b[s] = L1 % 2;
        L1 /= 2;
    }
    for (i = 1; i < s; i++) sum += e[(i + 1) / 2 - 1];
    if (s == 1) sum += 1;
    else if (s % 2 == 0) {
        k = s / 2;
        for (i = e[k - 1]; i <= e[k] - 1; i++) {
            L1 = i * e[k] + f(i);
            if (L1 <= L) sum++;
            else break;
        }
    } else {
        k = (s - 1) / 2;
        for (i = e[k - 1]; i <= e[k] - 1; i++) {
            L1 = i * e[k + 1] + f(i);
            if (L1 <= L) sum++;
            else break;
            L1 = i * e[k + 1] + e[k] + f(i);
            if (L1 <= L) sum++;
            else break;
        }
    }
    printf("%lu\n", sum);
    return 0;
}                                 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值