http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1237
sol:
本来已经不想做裸题了,但是之前的题总是要调一下才能过,就很不优美
这题终于一遍过了,感觉差不多把调试的坑点给找完了。
杜教筛的精髓似乎也掌握到一点了。
简单反演
∑ndd∑ndi∑ndj(i,j)=1
∑
d
n
d
∑
i
n
d
∑
j
n
d
(
i
,
j
)
=
1
∑ndd(2(∑ndjϕ(i))−1)
∑
d
n
d
(
2
(
∑
j
n
d
ϕ
(
i
)
)
−
1
)
筛一下phi。这里的phi我已经不是用tangls的那种推导方式了,而是使用了套路的推导方式,感觉确实已经很通用了。
#include<iostream>
#include<string>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<cmath>
using namespace std;
typedef long long ll;
ll n;
inline int read()
{
char c;
bool pd=0;
while((c=getchar())>'9'||c<'0')
if(c=='-') pd=1;
int res=c-'0';
while((c=getchar())>='0'&&c<='9')
res=(res<<3)+(res<<1)+c-'0';
return pd?-res:res;
}
const int N=1e6;
const int pyz=1e9+7;
int inv2;
int phi[N+7],s[N+7];
inline int ksm(int s,int t)
{
int res=1;
while(t)
{
if(t&1) res=(ll)res*s%pyz;
s=(ll)s*s%pyz;
t>>=1;
}
return res;
}
inline get_f(ll x)
{
if(x<=N) return phi[x];
if(s[n/x]) return s[n/x];
s[n/x]=(ll)x%pyz*(x%pyz+1)%pyz*inv2%pyz;
ll a,b;
for(ll i=2;i<=x;++i)
{
a=x/i;
b=x/a;
s[n/x]=(s[n/x]-(ll)get_f(a)*((b-i+1)%pyz)%pyz+pyz)%pyz;
i=b;
}
return s[n/x];
}
int prime[N];
bool is[N+7];
int main()
{
// freopen("1237.in","r",stdin);
// freopen(".out","w",stdout);
cin>>n;
inv2=ksm(2,pyz-2);
ll a,b,ans=0;
phi[1]=1;
for(int i=2;i<=N;++i)
{
if(!is[i]) prime[++prime[0]]=i,phi[i]=i-1;
for(int j=1;j<=prime[0]&&i*prime[j]<=N;++j)
{
is[i*prime[j]]=1;
if(!(i%prime[j]))
{
phi[i*prime[j]]=phi[i]*prime[j];
break;
}
phi[i*prime[j]]=phi[i]*(prime[j]-1);
}
phi[i]=(phi[i-1]+phi[i])%pyz;
}
for(ll i=1;i<=n;++i)
{
a=n/i;
b=n/a;
ans=(ans+(i+b)%pyz*((b-i+1)%pyz)%pyz*inv2%pyz*(2*get_f(a)%pyz-1)%pyz)%pyz;
i=b;
}
ans=(ans+pyz)%pyz;
cout<<ans;
}