1 条题解
-
0
考察
$$\sum_{i=1}^{n} lcm(i,n)=\sum_{i=1}^{n} in/gcd(i,n)$$那我们可以计算对于每个作为时,它对答案的贡献,就有
$$=n\sum_{d|n}\sum_{i=1}^{n} \frac{i}{d}[gcd(i,n)==d]$$考虑到如果,必然有为的倍数,因此不妨将i的意义转化为原来的,也即
$$=n\sum_{d|n}\sum_{i=1}^{n/d} \frac{i}{d}[gcd(id,n)==d]$$注意到表示中与互质的数的和,它等于(当时为)。证明如下:
当时,总是偶数,这是因为与互质的数总是成对出现。具体来说,假如与互质,与肯定也互质,它们的和是,并且有对。
于是上式化简为
设
那么对于每个,我们只要把加到中去,询问时再把最外面那个乘进去。复杂度是
#include <cstdio> const int N=1000000; int tot,p[N+5],phi[N+5]; long long ans[N+5]; bool flg[N+5]; void solve() { phi[1]=1; for(int i=2;i<=N;++i) { if(!flg[i]) p[++tot]=i,phi[i]=i-1; for(int j=1;j<=tot&&i*p[j]<=N;++j) { flg[i*p[j]]=1; if(i%p[j]==0) { phi[i*p[j]]=phi[i]*p[j]; break; } phi[i*p[j]]=phi[i]*(p[j]-1); } } for(int i=1;i<=N;++i) { for(int j=1;i*j<=N;++j) { ans[i*j]+=1LL*j*phi[j]/2; } } for(int i=1;i<=N;++i) ans[i]=1LL*i*ans[i]+i; } int main() { int T,n; solve(); for(scanf("%d",&T);T;--T) { scanf("%d",&n); printf("%lld\n",ans[n]); } return 0; }
- 1
信息
- ID
- 3891
- 时间
- 200ms
- 内存
- 128MiB
- 难度
- 10
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者