Chiaki Sequence Revisited
题意:给定一个序列,求其前缀和
思路:肯定打表找规律啊.. 可是你的出来吗?
一行分别对应的是i a[i] sum [i]
规律是,对于一个确定的n,我们可以求出它的a[n] . 知道a[n]就可以求其前缀和. 那么核心问题来了. 一个数出现的次数等于它能除多少个2... 是不是震惊.... 好. 现在对于9 来说 , 1倍数,2倍数,4倍数,8倍数,等差数列求和. ***... 以为做完了.结果取膜有毒
#include<bits/stdc++.h>
#define PI acos(-1.0)
#define pb push_back
#define F first
#define S second
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int N=1e5+5;
const int MOD=1e9+7;
template <class T>
bool sf(T &ret){ //Faster Input
char c; int sgn; T bit=0.1;
if(c=getchar(),c==EOF) return 0;
while(c!='-'&&c!='.'&&(c<'0'||c>'9')) c=getchar();
sgn=(c=='-')?-1:1;
ret=(c=='-')?0:(c-'0');
while(c=getchar(),c>='0'&&c<='9') ret=ret*10+(c-'0');
if(c==' '||c=='\n'){ ret*=sgn; return 1; }
while(c=getchar(),c>='0'&&c<='9') ret+=(c-'0')*bit,bit/=10;
ret*=sgn;
return 1;
}
ll pre[100];
ll n;
bool check(ll mid){
ll cnt=0;
for(int i=0;i<=62;i++){
cnt+=mid/pre[i];
if(cnt>=n-1) return true;
}
return cnt >= n-1;
}
int main(void){
pre[0]=1;
for(int i=1;i<=62;i++) pre[i]=2*pre[i-1];
ll inv2=(1000000000+8)/2;
int T;
sf(T);
while(T--){
scanf("%lld",&n);
ll l=max(1ll,n/2-100),r=min(n,n/2+100),ans;
while(l<=r){
ll mid=l+r >> 1;
if(check(mid)) r=mid-1,ans=mid;
else l=mid+1;
}
ll t=ans-1;
ll res=0;
ll tot=0;
for(int i=0;i<=62;i++){
if(pre[i]>t) break;
ll cnt=t/pre[i];
tot+=cnt;
res+=(pre[i]%MOD)*(cnt%MOD)%MOD*((cnt+1)%MOD)%MOD*(inv2%MOD); //cnt->1e18 每次都要取膜再乘.... fq
res%=MOD;
}
res= res + ans%MOD*(n-1-tot)%MOD;
res%=MOD;
res+=MOD;
res%=MOD;
printf("%lld\n",(res+1)%MOD);
}
return 0;
}