HDU 6304

 

HDU 6304_第1张图片

题解:

先把数列a打表找一下规律,发现(除了第一项1以外):

出现1次:1,3,5,7,9,11,13,15......

出现2次:2,6,10,14,18,22,26......

出现3次:4,12,20,28,36,44......

出现4次:8,24,40,56,72,88......

可以总结为:

每个分类都是等差数列

第i个分类的首项是2^{i-1},公差为2^{i}

根据n,二分出前n项中出现的数字的种数为x,然后根据以上规律,和等差数列的通项公式,求出前n项和。

例如:

n为9时,二分出x为5,即出现了数字1,2,3,4,5,然后根据出现的次数求和为:1+3+5+2*2+4*3+1=26.

代码:

#include
#define N 100010
#define INF 0x3f
#define LL long long
#define eps 1e-8
using namespace std;
const LL inv2=5e8+4;
const LL P=1e9+7;

LL sum(LL x)
{
    LL num=0;
    for (int i=1;i<63;i++) num+=((x+(1ll<<(i-1)))>>i)*i;
    return num;
}

int main()
{
    ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    LL T;
    cin>>T;
    while(T--)
    {
        LL n;
        cin>>n;
        if (n==1)cout<<1<1)
            {
                LL t=(l+r)>>1;
                if (sum(t)+1<=n) {ans=t;l=t;}
                else r=t;
            }
            LL m=sum(ans)+1;
            m=n-m;
            LL A=0;
            for (int i=1;i<=61;i++)
            {
                LL num=((ans+(1ll<<(i-1)))>>i)%P;
                LL a1=(1ll<<(i-1))%P;
                A=(A+  (a1*num%P +  (((num*((num-1+P)%P))%P)*inv2%P)*((1ll<

 

你可能感兴趣的:(2018,Training)