列表

详情


BC160. 小q的数列

描述

小q最近迷上了各种好玩的数列,这天,他发现了一个有趣的数列,其递推公式如下:

f[0]=0 f[1]=1;
f[i]=f[i/2]+f[i%2];(i>=2)

现在,他想考考你,问:给你一个n,代表数列的第n项,你能不能马上说出f[n]的值是多少,以及f[n]所代表的值第一次出现在数列的哪一项中?(这里的意思是:可以发现这个数列里某几项的值是可能相等的,则存在这样一个关系f[n'] = f[n] = f[x/2]+f[x%2] = f[x]...(n'<n<x) 他们的值都相等,这里需要你输出最小的那个n'的值)(n<10^18)

输入描述

输入第一行一个t
随后t行,每行一个数n,代表你需要求数列的第n项,和相应的n'
(t<4*10^5)

输出描述

输出每行两个正整数
f[n]和n',以空格分隔

示例1

输入:

2
0
1

输出:

0 0
1 1

原站题解

C 解法, 执行用时: 89ms, 内存消耗: 3728KB, 提交时间: 2022-07-17

#include <stdio.h>
#include <math.h>//分析题目可得,fn为n的二进制中1的个数
 
int main(){
    int t, count;
    long n;
    scanf("%d", &t);
    for(int i = 0; i < t; i++){
        scanf("%ld", &n);
        count = 0;
        while(n){
            count += n & 1 == 1? 1 : 0; //对应二进制1的个数  
            n >>= 1;//右移后赋值           
        }
        printf("%d %ld\n", count, (long)pow(2, count) - 1);
    }
    return 0;
}

C 解法, 执行用时: 89ms, 内存消耗: 3752KB, 提交时间: 2022-07-02

#include <stdio.h>
#include <math.h>
 
int main(){
    int t, count;
    long n;
    scanf("%d", &t);
    for(int i = 0; i < t; i++){
        scanf("%ld", &n);
        count = 0;
        while(n){
            count += n & 1 == 1? 1 : 0; //对应二进制1的个数  
            n >>= 1;           
        }
        printf("%d %ld\n", count, (long)pow(2, count) - 1);
    }
    return 0;
}

C 解法, 执行用时: 89ms, 内存消耗: 3820KB, 提交时间: 2022-06-14

// 首先理解题意 f[n]的值就是n转化为二进制中的1的个数 
// f(n)' 就是找最小项的话 可以看到是2的幂次-1
#include<stdio.h>
int main()
{
    long long t,n,i;
    scanf("%lld",&t);
    
    while(t--)
    {
        long long sum=0,num=0;
        scanf("%lld",&n);
        while(n)
        {
            sum++;
            n=n&(n-1);
        }
        for(i=0;i<sum;i++)
            num=num*2+1;
        printf("%lld %lld\n",sum,num);
    }
}

C 解法, 执行用时: 89ms, 内存消耗: 4888KB, 提交时间: 2022-07-15

//有变量n,n',f(n),f(n')共四个
//step1:将十进制数n转换为二进制数a
//step2:求二进制数a中1的个数x,f(n')=f(n)=x;
//step3:最早出现的n'就是2的0次方一直加到2的X次方(2的a次方-1;
#include<stdio.h>
int main()
{
    long long int t = 0;
    long long int n = 0;
    long long int i = 0;
    scanf("%lld",&t);
    while(t--)//通过while循环来打印t行数据
    {
        long long int a = 0;
        long long int b = 0;
        scanf("%lld",&n);//输入每行数据
        while(n)//每行数据进行操作
        {
            n=n&(n-1);//判断一个数据的二进制有多少个1
            a++;//每一个1就加加,a的结果等于f(n)
        }
        for(i=0;i<a;i++)
        {
            b=b*2+1;
        }
        printf("%lld %lld\n",a,b);
    }
    return 0;
}

C 解法, 执行用时: 90ms, 内存消耗: 3716KB, 提交时间: 2022-06-27

#include<stdio.h>
int main()
{
    long long int t = 0;
    long long int n = 0;
    long long int i = 0;
    scanf("%lld",&t);
    while(t--)//通过while循环来打印t行数据
    {
        long long int a = 0;
        long long int b = 0;
        scanf("%lld",&n);//输入每行数据
        while(n)//每行数据进行操作
        {
            n=n&(n-1);//判断一个数据的二进制有多少个1
            a++;//每一个1就加加,a的结果等于f(n)
        }
        for(i=0;i<a;i++)
        {
            b=b*2+1;
        }
        printf("%lld %lld\n",a,b);
    }
    return 0;
}

上一题