题目大意:给定 求 其中
总之就是求和公式不可用问题
1. 提公因式
,原式变为
2.
求出
3. 方便起见,我们定义自然数集上的函数
以及
,定义变量
4. 对于
,我们隔一个数提一次公因式,得到
5. 以此类推,我们得到
时,
6. 特殊地,当
时,有
显然成立
7. 我们通过画图发现,求和得到的
其实与
的二进制位相关
8. 通过更进一步观察,我们得到如下结论:
需要进行一次求和,当且仅当
二进制位当前位为
9. 再结合之前提公因式得到的结论,我们得到
在
倒数第
位为
时需要同
求和
10. 对于
与
我们可以在
的复杂度内完成预处理
11. 于是我们就得到了这份时间复杂度最差为
的代码
void solve2(){
n%=MOD;
a[0]=b[0]=1;
a[1]=n;
for(int i=2;i<=60;++i) a[i]=a[i-1]*a[i-1]%MOD;
for(int i=1;i<=60;++i) b[i]=b[i-1]*(a[i]+1)%MOD;
long long ans=0,w=n,pw=1;
r=r-l+1;
while(l){
if(l&1) pw=pw*w%MOD;
l>>=1,w=w*w%MOD;
}int t=0;
while(r){
if(r&1){
long long y=r-1,q=1;w=a[t+1];
while(y){
if(y&1) q=q*w%MOD;
y>>=1,w=w*w%MOD;
}ans=(ans+q*b[t])%MOD;
}r>>=1,++t;
}printf("%lld\n",ans*pw%MOD);
}