HDU 6304(找规律)

Chiaki Sequence Revisited

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 634    Accepted Submission(s): 132


 

Problem Description

Chiaki is interested in an infinite sequence a1,a2,a3,..., which is defined as follows: 

an={1an−an−1+an−1−an−2n=1,2n≥3


Chiaki would like to know the sum of the first n terms of the sequence, i.e. ∑i=1nai. As this number may be very large, Chiaki is only interested in its remainder modulo (109+7).

 

Input

There are multiple test cases. The first line of input contains an integer T (1≤T≤105), indicating the number of test cases. For each test case:
The first line contains an integer n (1≤n≤1018).

 

Output

For each test case, output an integer denoting the answer.

 

Sample Input

 

10 1 2 3 4 5 6 7 8 9 10

 

Sample Output

 

1 2 4 6 9 13 17 21 26 32

 

Source

2018 Multi-University Training Contest 1

找规律

一开始看了两小时OEIS,屁用没有。。。。。。。

每个数出现的次数是log(lowbit(i))+1次

那么,可以二分出a[n]的值

对于同样的lowbit,构成了一个等差数列

求和即可。

#include<bits/stdc++.h>
#define mp make_pair
#define fir first
#define se second
#define ll long long
const int maxn=3e5+10;
const ll mod=1e9+7;
using namespace std;
ll num[100],p[100];
void init(){
    num[0]=p[0]=1;
    for (int i=1;i<=63;i++){
        num[i]=2*num[i-1]+1;
        p[i]=p[i-1]*2;
    }
}
ll n;
ll inv2=(mod+1)/2;
ll getsum(ll pos){
    ll sum=0;
    for (ll i=1;i<=pos;i*=2){
        ll num=(pos-i)/(2*i);
        ll Max=i+num*(2*i);
        //cout<<"nnum="<<num<<endl;
       // cout<<"Max="<<Max<<endl;
        num=(num+1)%mod;
        Max=(Max+i)%mod;
        Max=Max*num%mod;
        Max=Max*inv2%mod;
        Max=Max*(__builtin_ctz(i)+1)%mod;
        sum=(sum+Max)%mod;
    }
    return (sum+1)%mod;
}
int main(){
    int t;
    scanf("%d",&t);
    init();
    while (t--){
        scanf("%lld",&n);
        ll pos=0;
        n--;
        if (!n){
            printf("1\n");
            continue;
        }
        ll temp=n;
        for (int i=62;i>=0;i--){
            if (temp>=num[i]){
                temp-=num[i];
                pos+=p[i];
            }
        }
        //cout<<"pos="<<pos<<endl;
        ll sum1=getsum(pos);
        if (temp){
            sum1=(sum1+temp%mod*(pos+1)%mod)%mod;
        }
        printf("%lld\n",sum1);
    }

    return 0;
}

猜你喜欢

转载自blog.csdn.net/wyj_alone_smile/article/details/81177111