51nod 1220 约数之和

题意:\(\sum_{i=1}^n \sum_{j=1}^n \sigma(i\times j), n \leq 1e9\)

题解:惭愧。

说到约数和,我们可能能想起约数个数和:\(d(i\times j)=\sum_{p|i}\sum_{q|j}[(x,y)==1]\)

我们考虑把每个因子一一映射。

如果 \(i\times j\) 的因子 \(k\) 中有一个因子 \(p^c\)\(i\) 中有因子 \(p^a\)\(j\) 中有因子 \(p^b\) 。我们规定:

  • 如果 \(c\leq a\),那么在 \(i\) 中选择。
  • 如果 \(c>a\),那么我们把 \(c\) 减去 \(a\),在 \(j\) 中选择 \(p^{c-a}\)(在 \(j\) 中选择 \(p^e\) 表示的是 \(p^{a+e}\)

对于 \(i\times j\) 的因子 \(k\) 的其他因子同理。于是对于任何一个 \(k\) 有一个唯一的映射,且每一个选择对应着唯一的 \(k\)
通过如上过程,我们发现:对于 \(i\times j\) 的因子 \(k=\prod {p_i}^{c_i}\) ,我们不可能同时在 \(i\)\(j\) 中选择 \(p_i\) (优先在 \(i\) 中选择,如果不够就只在 \(j\) 中选择不够的指数),故 \(x\)\(y\) 必须互质。

等式得证。

From Siyuan@luogu

有一个式子: \(\sigma(i\times j)=\sum_{x|i}\sum_{y|j} \frac{i}{x}y[(x,y)==1]\)

证明仍然类似上面考虑,如果 \(i\times j\) 的因子 \(k\) 中有一个因子 \(p^c\)\(i\) 中有因子 \(p^a\)\(j\) 中有因子 \(p^b\) 。我们规定:

  • 如果 \(c\leq a\),那么在 \(i\) 中选择,这个时候 \(x\) 中包含 \(p^{a-c}\) ,所以此时 \(\frac{i}{x}\) 贡献了 \(p^c\)
  • 如果 \(c>a\),那么我们把 \(c\) 减去 \(a\),在 \(j\) 中选择 \(p^{c-a}\) ,即此时 \(y\) 中包含 \(p^{c-a}\)

此时对于 \(i\times j\) 的因子 \(k=\prod {p_i}^{c_i}\) 仍然有唯一的映射。

所以可以化式子了:

\(=\sum_{i=1}^n \sum_{j=1}^n \sum_{x|i} \sum_{y|j} \frac{i}{x}y [(x,y)==1]\)

\(=\sum_{i=1}^n \sum_{j=1}^n \sum_{x|i} \sum_{y|j} \frac{i}{x}y \sum_{d|gcd(x,y)} \mu(d)\)

$=\sum_{i=1}^n \sum_{j=1}^n \sum_{d|gcd(i,j)} \mu(d) \sum_{x|\frac{i}{d}} \sum_{y|\frac{j}{d}} \frac{i}{x}y $

$=\sum_{d=1}^{n}d \mu(d) \sum_{i=1}^{\frac{n}{d}} \sum_{j=1}^{\frac{n}{d}} \sum_{x|i} \sum_{y|j} \frac{i}{x}y $

$=\sum_{d=1}^{n}d \mu(d)\ (\sum_{i=1}^{\frac{n}{d}} \sum_{x|i} \frac{i}{x})\ (\sum_{j=1}^{\frac{n}{d}} \sum_{y|j} y) $

$=\sum_{d=1}^{n}d \mu(d)\ (\sum_{i=1}^{\frac{n}{d}} \sigma(i))^2 $

然后 \(\sum_{i=1}^{\frac{n}{d}} \sigma(i)\) 注意到ta的上界显然是可以除法分块的,此时我们再在前头套个杜教筛即可。
最后就是 \(\sum_{i=1}^n \sigma(i) = \sum_{i=1}^n i\lfloor \frac{n}{i} \rfloor\) ,表示 \(i\) 出现了几次。

#pragma GCC optimize(2)
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring> 
#define R register int
#define ll long long
using namespace std;
namespace Luitaryi {
const int N=1000000,M=1000000007;
int n,cnt;
int mu[N+10],p[N>>1];
ll s[N+10],c[N+10];
bool vis[N+10];
inline void pre(int n) {
  mu[1]=1,s[1]=1;
  for(R i=2;i<=n;++i) {
    if(!vis[i]) p[++cnt]=i,mu[i]=-1,s[i]=i+1,c[i]=i+1;
    for(R j=1,k;j<=cnt&&i*p[j]<=n;++j) {
      k=i*p[j]; vis[k]=true;
      if(i%p[j]==0) {
        c[k]=c[i]*p[j]+1;
        s[k]=s[i]/c[i]*c[k];
        break;
      } mu[k]=-mu[i];
      c[k]=p[j]+1;
      s[k]=s[i]*(p[j]+1);
    }
  }
  for(R i=1;i<=n;++i) mu[i]=(mu[i-1]+mu[i]*i+M)%M;
  for(R i=1;i<=n;++i) s[i]=(s[i-1]+s[i])%M;
}
int memmu[64000],SZ;
#define sqr(x) (1ll*(x)*(x+1)/2%M)
inline int calmu(int x) {
  if(x<=N) return mu[x];
  R& ret=x>SZ?memmu[SZ+n/x]:memmu[x];
  if(ret!=memmu[0]) return ret;
  R ans=1,lst=1,now;
  for(R l=2,r;l<=x;l=r+1) {
    r=x/(x/l),now=sqr(r);
    ans=(ans-1ll*(now-lst)*calmu(x/l))%M;
    lst=now;
  } 
  return ret=(ans+M)%M;
}
inline int cals(int x) {
  if(x<=N) return s[x];
  R ret=0,lst=0,now;
  for(R l=1,r;l<=x;l=r+1) {
    r=x/(x/l);
    now=sqr(r);
    ret=(ret+1ll*(now-lst)*(x/l))%M;
    lst=now;
  } return (ret+M)%M;
}
inline void main() {
  pre(N); scanf("%d",&n); SZ=sqrt(n);
  memset(memmu,0xcf,sizeof memmu);
  R ans=0,lst=0,now,tmp;
  for(R l=1,r;l<=n;l=r+1) { 
    r=n/(n/l),now=calmu(r),tmp=cals(n/l);
    tmp=1ll*tmp*tmp%M;
    ans=(ans+1ll*(now-lst)*tmp)%M;
    lst=now;
  } printf("%d\n",(ans+M)%M);
}
} signed main() {Luitaryi::main(); return 0;}

2019.12.23

posted @ 2019-12-23 19:29  LuitaryiJack  阅读(283)  评论(0编辑  收藏  举报