Chiaki Sequence Revisited[找规律]

Chiaki Sequence Revisited

题意:给定一个序列,求其前缀和

思路:肯定打表找规律啊.. 可是你的出来吗?

一行分别对应的是i  a[i]   sum [i]

规律是,对于一个确定的n,我们可以求出它的a[n] . 知道a[n]就可以求其前缀和.   那么核心问题来了. 一个数出现的次数等于它能除多少个2... 是不是震惊.... 好. 现在对于9 来说 , 1倍数,2倍数,4倍数,8倍数,等差数列求和. fuck...  以为做完了.结果取膜有毒

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

猜你喜欢

转载自blog.csdn.net/Haipai1998/article/details/81182935