离退役不远了,我依然很菜很菜,所以以后博客不再面向对象了,只为自己看懂。
题面
题意:求
∑i=1n∑j=1nmax(i,j)σ1(ij)
其中 σ1(x) 为x的约数和。
分类讨论
2∑i=1n∑j=1iiσ1(ij)−∑i=1niσ1(i2)
考虑
∑i=1n∑j=1iiσ1(ij)
由kscla的数表,有
=∑i=1ni∑j=1i∑a|i∑b|ja∗j/b[(a,b)=1]
先枚举a,到i,到b,到j,在把中括号用 μ 换,
=∑d=1nμ(d)d2∑i=1⌊nd⌋i2∑a=1⌊nid⌋a∑j=1ai∑b=1⌊aij⌋b
设右半部分为 f(⌊nd⌋) ,有
=∑d=1nμ(d)d2f(⌊nd⌋)
考虑f,有
f(x)=∑n=1xn∑i=1nσ21(i)
根据杜教筛的柿子和套路,将f差分,设为g,有
ans(n)=∑d=1n∑i|di2∗μ(i)∗f(di)
复杂度nln(n)。
这是 Kscla的博客,两篇都有错,对着看就好了。
这个T了,也懒得调了。
#include <iostream>
#include <fstream>
#include <algorithm>
#include <cmath>
#include <ctime>
#include <cstdio>
#include <cstdlib>
#include <cstring>
using namespace std;
#define mmst(a, b) memset(a, b, sizeof(a))
#define mmcp(a, b) memcpy(a, b, sizeof(b))
typedef long long LL;
const int N=1001000,nn=1000000;
LL mo=1e9+7;
int T,n;
LL prime[N],num,u[N],f[N],miu[N];
LL g[N],h[N],p[N];
int ans[N],c[N],hh[N];
bool b[N];
void read(int &hy)
{
hy=0;
char cc=getchar();
while(cc<'0'||cc>'9')
cc=getchar();
while(cc>='0'&&cc<='9')
{
hy=(hy<<3)+(hy<<1)+cc-'0';
cc=getchar();
}
}
int main()
{
p[1]=miu[1]=u[1]=f[1]=1;
for(int i=2;i<=nn;i++)
{
if(!b[i])
{
prime[++num]=i;
u[i]=i;
miu[i]=-1;
f[i]=i+1;
p[i]=((LL)i*i%mo+i+1)%mo;
}
for(int j=1;j<=num&&prime[j]*i<=nn;j++)
{
LL pj=prime[j];
int ipj=i*pj;
b[ipj]=1;
if(i%pj==0)
{
u[ipj]=u[i]*pj;
f[ipj]=(f[i]+f[i/u[i]]*u[i*pj])%mo;
p[ipj]=(p[i]+p[i/u[i]]*(pj+1)%mo*u[ipj]%mo*u[i]%mo)%mo;
miu[ipj]=0;
break;
}
f[ipj]=f[i]*f[pj]%mo;
p[ipj]=p[i]*p[pj]%mo;
u[ipj]=pj;
miu[ipj]=-miu[i];
}
}
for(int i=1;i<=nn;i++)
p[i]=p[i]*i%mo;
for(int i=1;i<=nn;i++)
p[i]=(p[i]+p[i-1])%mo;
for(int i=1;i<=nn;i++)
g[i]=(g[i-1]+f[i])%mo;
for(int i=1;i<=nn;i++)
h[i]=g[i]*i%mo*f[i]%mo;
for(int i=1;i<=nn;i++)
miu[i]=(miu[i]*i*i%mo+mo)%mo;
for(int i=1;i<=nn;i++)
c[i]=(int)miu[i];
for(int i=1;i<=nn;i++)
hh[i]=(int)h[i];
for(int i=1;i<=nn;i++)
for(int k=i;k<=nn;k+=i)
ans[k]=(ans[k]+(LL)hh[k/i]*c[i]%mo)%mo;
for(int i=1;i<=nn;i++)
ans[i]=(ans[i-1]+ans[i])%mo;
scanf("%d",&T);
for(int i=1;i<=T;i++)
{
read(n);
int tu=(2*ans[n]%mo-p[n]+mo)%mo;
printf("Case #%d: %d\n",i,tu);
}
return 0;
}