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).
The first line contains an integer n (1≤n≤1018).
思路
先对aiai打表找一下规律会发现每个数字出现的个数有如下的关系
12345678⋮12131214⋮
1122314351627184⋮⋮
思考一下就会发现对于数字ii他出现的个数是ii转化为二进制后最后一位1在位置,也就是
log2(lowbit(i))+1log2(lowbit(i))+1,我们把这个函数记作f(i)=log2(lowbit(i))+1f(i)=log2(lowbit(i))+1
接下来我们要解决的问题是给你nn如何求出anan,我们记f(i)f(i)的前缀和为g(i)g(i),如果知道了n刚好大于下标为ii的前缀和就可以确定anan是哪一个数了,前缀和g(i)g(i)是一个递增的函数,所以我们可以用二分的方法求出ii的值,下面的问题是然后求得g(i)g(i)的表达式
关于f(i)f(i)有两性质
{f(2i+1)=1f(2i)=f(i)+1
{f(2i+1)=1f(2i)=f(i)+1
利用这两个性质我们可以对g(n)g(n)进行化简
g(2n)=∑i=12nf(i)
g(2n)=∑i=12nf(i)
=∑i=1nf(2i)+∑i=0n−1f(2i+1)
=∑i=1nf(2i)+∑i=0n−1f(2i+1)
=n+∑i=1n(f(i)+1)
=n+∑i=1n(f(i)+1)
=∑i=1nf(i)+2n
=∑i=1nf(i)+2n
=g(n)+2n
=g(n)+2n
即g(n)=g(n2)+ng(n)=g(n2)+n
也就是说我们如果知道下标ii我们就可以就可以通过递归求出前缀和,有了前缀和的求解方式我们就可以通过二分来找出数字nn所对应的anan的值了,也就是第anan项的前缀和
那么我们找到了anan又如何求出和SnSn呢,我们先观察函数g(an)g(an)的值
g(an)=11+22+31+43+51+62+71+84+91+102⋯⋯
12345678910⋯g(an)=1+2+1+3+1+2+1+4+1+2⋯
我们已经知道了最后一项也就是anan的值,那我们观察一下会发现一些等差数列
12436125102071428⋮91836⋯⋯⋯∗1∗2∗3
13579⋯∗126101418⋯∗2412202836⋯∗3⋮
也就是是每个数字出现的个数都符合一个等差数列的关系,设求出的anan的值为xx
那么每一个等差数列的项数就为x−2i−12i+1x−2i−12i+1,其中ii代表是哪一个数列,那么我们就可以求得数列的末项然后用等差数列求和公式就可以求出小于anan中出现的数的和了,然后每个序列又有一个出现次数,再乘上这个序列出现的次数就可以得到最后的答案了
注意的是二分答案的时候为了不TLE要在n2n2的附近查找,序列的规律是除第一项之后的数的规律,所以一开始n-1,最后的答案再加上这个1