题解:

先把数列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个分类的首项是,公差为

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

例如:

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

代码:

#include<bits/stdc++.h>
#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<<endl;else if (n==2)cout<<2<<endl;else if (n==3)cout<<4<<endl;else
        {
            LL l=max(1ll,n/2-50),r=min(n,n/2+50);
            LL ans=0;
            while(r-l>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<<i)%P)%P  )  *i%P )%P;
            }
            for (int i=1;i<=m;i++) A=(A+ans+1)%P;
            cout<<(A+1)%P<<endl;
        }
    }
    return 0;
}