CCPC2021威海 CF103428I Distance 题解
题目描述
一张 \(n\) 个点的图,编号 \(1\sim n\) 。若 \(\frac yx\in\text{prime}\) ,则在图中添加一条连接 \(x,y\) ,权值为 \(\frac yx\) 的边。
求 \(\sum_{i=1}^n\sum_{j=1}^ndis(i,j)\) ,对 \(10^9+7\) 取模。
数据范围
- \(1\le n\le 10^{11}\) 。
时间限制 \(\texttt{4s}\) ,空间限制 \(\texttt{256MB}\) 。
分析
做质因数分解 \(\frac yx=\prod_{i=1}^kp_i^{a_i}\) ,则 \(dis(i,j)=\sum_{i=1}^k|a_i|p_i\) 。
对每个质数 \(p\) 分别统计贡献,枚举幂次 \(e\) ,统计 \(v_p(i)\lt e\) 且 \(v_p(j)\ge e\) 的所有点对 \((i,j)\) ,则每对 \((x,y)\) 刚好被统计 \(|a_i|\) 次。
于是答案为:
\[2\sum_{p\in\text{prime}}p\cdot\sum_{e\ge 1}(n-\lfloor\frac n{p^e}\rfloor)\lfloor\frac n{p^e}\rfloor\\
\]
对 \(e\ge 2\) ,有 \(p\le\sqrt n\) ,直接枚举 \((p,e)\) ,时间复杂度 \(\mathcal O(\sqrt n)\) 。
对 \(e=1\) ,用 \(\min25\) 筛统计质数在 \(n\) 的整除分块点处的前缀和,时间复杂度 \(\mathcal O(\frac{n^{0.75}}{\log n})\) 。
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int maxn=6.4e5+5,mod=1e9+7,inv2=(mod+1)>>1;
int B,m,n,cnt,res;
int p[maxn],id1[maxn],id2[maxn];
int g[maxn],s[maxn],val[maxn];
bitset<maxn> b;
void init(int n)
{
for(int i=2;i<=n;i++)
{
if(!b[i]) p[++cnt]=i;
for(int j=1;j<=cnt&&i*p[j]<=n;j++)
{
b[i*p[j]]=1;
if(i%p[j]==0) break;
}
}
for(int i=1;i<=cnt;i++) s[i]=(s[i-1]+p[i])%mod;
}
int id(int x)
{
return x<=B?id1[x]:id2[n/x];
}
signed main()
{
scanf("%lld",&n),init(B=sqrt(n));
for(int l=1,r=0;l<=n;l=r+1)
{
int x=n/l;
r=n/x,val[++m]=x,x<=B?id1[x]=m:id2[n/x]=m;
x%=mod,g[m]=(x*(x+1)%mod*inv2-1)%mod;
}
for(int j=1;j<=cnt;j++)
for(int i=1;p[j]*p[j]<=val[i];i++)
{
int k=id(val[i]/p[j]);
g[i]=(g[i]-p[j]*(g[k]-s[j-1]))%mod;
}
for(int i=m;i>=1;i--)
{
int k=id(n/val[i]);
res=(res+((n-val[i])%mod)*(val[i]%mod)%mod*(g[k]-g[k+1]))%mod;
}
for(int i=1;i<=cnt;i++)
for(int x=p[i]*p[i];x<=n;x*=p[i])
res=(res+p[i]*(n-n/x)%mod*((n/x)%mod))%mod;
printf("%lld\n",2*(res+mod)%mod);
return 0;
}
本文来自博客园,作者:peiwenjun,转载请注明原文链接:https://www.cnblogs.com/peiwenjun/p/19445084
浙公网安备 33010602011771号