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;
}