多校1 hdu 6304 Chiaki Sequence Revisited (规律题)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6304

题解:

参考链接:https://blog.csdn.net/qq_36258516/article/details/81185932

https://blog.csdn.net/luyehao1/article/details/81184708

我们先打个表,

出现1次的:1,  3,5,7,9,11,13...... 公差为2的等差数列

出现2次的:2 ,6,10,14,18.......   公差为4的等差数列

出现3次的:4,12,20,28,36......  公差为8的等差数列

出现4次的:8 ,24,40,56,72.....  公差为16的等差数列

[1,n]  出现的次数以此为 1 2 1 3 1 2 1 4 1 2 1 3 1 2 1 5 ... 发现1...(2^(i-1)-1)出现的次数=2^(i-1)+1...(2^i-1)出现的次数,而2^(i-1)出现的次数+1=2^i出现的次数。由此可以推得,前2^i个数出现的次数和=前2^(i-1)个数出现的次数和*2+1

然后,我们先求出x,x表示当a[n]及以前出现的且已经完全结束的最大整数(ex. 若a[n]=8,但a[n+1]=8,则x=7)。

我们可以发现,数字num出现的次数是其二进制末尾0的个数+1

 

这题的规律真。。。。TM难弄。

 


 

#include<cstdio>
#include<algorithm>
#include<cstring>

using namespace std;
typedef long long LL;

const LL mod=1000000007;

LL inv=(mod+1)/2;
LL ans[110],num[110];

LL solve(LL x)
{
    LL sum=0;

    for(LL i=1;i<=x;i*=2) ///等差数列求和,每个i代表首项
    {
        LL item=(x-i)/(i*2);
        LL last=i+item*i*2;

        item=(item+1)%mod;

        last=((i+last)%mod*item)%mod*inv%mod;
        last=last*(__builtin_ctz(i)+1)%mod;
        sum=(sum+last)%mod;
    }
    return (sum+1)%mod;
}

int main()
{

    ans[0]=num[0]=1;

    for(int i=1;i<=63;i++)
        ans[i]=ans[i-1]*2+1,num[i]=num[i-1]*2;
        ///预处理前num[i]数字中,出现的次数为ans[i]
    int ncase;
    scanf("%d",&ncase);

    while(ncase--)
    {
        LL n;

        scanf("%lld",&n);

        n--;///因为我们是从第二个当成第一个开始的(1) 1 2 1 3 1 2 1 4
        if(n==0){
            puts("1");continue;
        }

        LL item=n,sum=0;

        for(int i=62;i>=0;i--){

            if(item>=ans[i]){
                item-=ans[i];
                sum+=num[i];///表示前num[i]个数中,出现了ans[i]次
            }
        }
//        printf("item=%lld,sum=%lld",item,sum);
        LL t=solve(sum);

        t=(t+item*(sum+1))%mod;

        printf("%lld\n",t);
    }


    return 0;
}

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值