这题其实就是反演一波就好了(那你还推了一下午+一晚上),不过第一次碰到(O(nlog n))预处理分块和式的方法……
不知为啥我跟唐教主的题解推的式子不太一样……(虽然本质上可能是相同的吧)
那就写一写好了,顺便骗点访问量(逃
[egin{align}
onumber ext{Let}space A=&sum_{i=1}^nsum_{j=1}^i isigma_1(ij),B=sum_{i=1}^n isigma_1(i^2)\
onumber ext{Then}space Ans=&2A-B\
end{align}]
[egin{align}
onumber A=&sum_{i=1}^nsum_{j=1}^i isigma_1(ij)\
onumber =&sum_{i=1}^nsum_{j=1}^i isum_{p|i}sum_{q|j}[(p,q)=1]frac{pj}q\
onumber =&sum_{d=1}^nmu(d)sum_{i=1}^nsum_{j=1}^i isum
_{p|i}sum_{q|j}[d|(p,q)]frac{pj}q\
onumber =&sum_{d=1}^nmu(d)sum_{d|p}pleft(sum_{p|i}i
ight)sum_{d|q}sum_{q|j}^i frac j q\
onumber =&sum_{d=1}^nmu(d)sum_{p=1}^{leftlfloorfrac n d
ight
floor}dpleft(sum_{p|i}^{leftlfloorfrac n d
ight
floor}di
ight)sum_{q=1}^{leftlfloorfrac n d
ight
floor}sum_{q|j}^i frac{dj}{dq}\
onumber =&sum_{d=1}^nmu(d)sum_{p=1}^{leftlfloorfrac n d
ight
floor}dpleft(sum_{p|i}^{leftlfloorfrac n d
ight
floor}di
ight)sum_{q=1}^isum_{q|j}^i frac j q\
onumber =&sum_{d=1}^nmu(d)d^2sum_{i=1}^{leftlfloorfrac n d
ight
floor}ileft(sum_{p|i}p
ight)sum_{j=1}^isum_{q|j}frac j q\
onumber =&sum_{d=1}^nmu(d)d^2sum_{i=1}^{leftlfloorfrac n d
ight
floor}isigma_1(i)sum_{j=1}^isigma_1(j)\
onumber =&sum_{d=1}^nmu(d)d^2sum_{i=1}^{leftlfloorfrac n d
ight
floor}isigma_1(i)S_{sigma_1}(i)
end{align}]
[egin{align}
onumber B=&sum_{i=1}^n isigma_1(i^2)\
onumber =&sum_{i=1}^n isum_{p|i}sum_{q|j}[(p,q)=1]frac{pi}q\
onumber =&sum_{d=1}^nmu(d)sum_{i=1}^n isum_{p|i}sum_{q|j}[d|(p,q)]frac{pi}q\
onumber =&sum_{d=1}^nmu(d)sum_{d|i} isum_{d|p|i}sum_{d|q|j}frac{pi}q\
onumber =&sum_{d=1}^nmu(d)d^2sum_{i=1}^{leftlfloorfrac n d
ight
floor} isum_{p|i}sum_{q|j}pfrac i q\
onumber =&sum_{d=1}^nmu(d)d^2sum_{i=1}^{leftlfloorfrac n d
ight
floor} isigma_1^2(i)\
end{align}]
[Ans=2A-B\=sum_{d=1}^nmu(d)d^2sum_{i=1}^{leftlfloorfrac n d
ight
floor}isigma_1(i)left(2S_{sigma_1}(i)-sigma_1(i)
ight)
]
到了这里就可以用(O(n))预处理+单次询问(O(sqrt n))的经典做法了,总复杂度(O(n+Tsqrt n))。
但是这样还是有点慢……常数优化到一定程度之后极限数据仍然要跑2s+(卡常技巧不行……逃),看来常数优化玩不了了,只能试试别的做法。
考虑枚举(d)和(k=leftlfloorfrac n d
ight
floor),并考虑它们能对哪些(n)作出贡献。不难发现,如果(leftlfloorfrac n d
ight
floor=k),那么一定有(nin[dk,d(k+1))),再稍加观察就能得到每对((d,k))都会对(ge dk)的所有(n)作出贡献,因此枚举所有(d,k)并差分一下,最后求一遍前缀和即可。
这样就能做到预处理(O(nlog n)),询问(O(1))了,不用卡常也可以过。
#pragma GCC optimize("Ofast")
#include<stdio.h>
#define int unsigned
using namespace std;
template<class T>inline void readint(T &v){
int x=0;
char c=getchar();
while(c<48)c=getchar();
while(c>47){
x=x*10+(c^48);
c=getchar();
}
v=x;
}
template<class T>inline void writeint(T x){
static int a[25];
if(!x)putchar('0');
else{
int i=0;
while(x){
a[++i]=x%10;
x/=10;
}
while(i)putchar(a[i--]^48);
}
}
const int maxn=1000010,p=1000000007;
void get_table(int);
bool notp[maxn];
int prime[maxn],mu[maxn],sigma[maxn],ans[maxn],f[maxn];
signed main(){
get_table(1000000);
int T;
readint(T);
for(int k=1;k<=T;k++){
int n;
readint(n);
putchar('C');
putchar('a');
putchar('s');
putchar('e');
putchar(' ');
putchar('#');
writeint(k);
putchar(':');
putchar(' ');
writeint(ans[n]);
putchar('
');
}
return 0;
}
void get_table(int n){
mu[1]=sigma[1]=1;
for(int i=2;i<=n;i++){
if(!notp[i]){
prime[++prime[0]]=i;
mu[i]=-1;
sigma[i]=i+1;
f[i]=1;
}
for(int j=1;j<=prime[0]&&i*prime[j]<=n;j++){
notp[i*prime[j]]=true;
if(i%prime[j]){
mu[i*prime[j]]=-mu[i];
sigma[i*prime[j]]=(long long)sigma[i]*(prime[j]+1)%p;
f[i*prime[j]]=i;
}
else{
if(f[i]==1)sigma[i*prime[j]]=((long long)prime[j]*sigma[i]+1)%p;
else sigma[i*prime[j]]=(long long)sigma[i/f[i]*prime[j]]*sigma[f[i]]%p;
f[i*prime[j]]=f[i];
}
}
}
for(int i=2,sum=1;i<=n;i++){
sum+=sigma[i];
if(sum>=p)sum-=p;
sigma[i]=(long long)i*sigma[i]%p*(2ll*sum-sigma[i]+p)%p;
}
for(int i=1;i<=n;i++){
int t=((long long)i*i%p*(signed)mu[i]+p)%p;
for(int j=1;i*j<=n;j++)ans[i*j]=(ans[i*j]+(long long)t*sigma[j])%p;
}
for(int i=2;i<=n;i++){
ans[i]+=ans[i-1];
if(ans[i]>=p)ans[i]%=p;
}
}