• bzoj 3994 [SDOI2015]约数个数和——反演


    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3994

    ( d(i*j)=sumlimits_{x|i}sumlimits_{y|j}e(gcd(frac{i}{x},y)==1) )

    即把 i*j 的约数质因数分解后,把质因数尽量放在 x 那里,以防重复。

    ( ans = sumlimits_{i=1}^{n}sumlimits_{j=1}^{m}sumlimits_{x|i}sumlimits_{y|j}e(gcd(frac{i}{x},y)==1) )

      ( = sumlimits_{i=1}^{n}sumlimits_{j=1}^{m}sumlimits_{x|i}sumlimits_{y|j}sumlimits_{d|x , d|y}mu(d) )

    注意这里不要把 d 提前,要把 x , y 提前。

      ( = sumlimits_{x=1}^{n}sumlimits_{y=1}^{m}leftlfloor frac{n}{x} ight floor leftlfloor frac{m}{y} ight floor sumlimits_{d|x , d|y}mu(d) )

      ( = sumlimits_{d=1}^{n}mu(d)sumlimits_{i=1}^{frac{n}{d}}sumlimits_{j=1}^{frac{m}{d}}leftlfloor frac{n}{i*d} ight floor leftlfloor frac{m}{j*d} ight floor )

    这时要发现右边的求和边界与值的一些共同点。

      ( = sumlimits_{d=1}^{n}mu(d)sumlimits_{i=1}^{frac{n}{d}}leftlfloor frac{leftlfloorfrac{n}{d} ight floor}{i} ight floorsumlimits_{j=1}^{frac{m}{d}} leftlfloor frac{leftlfloorfrac{m}{d} ight floor}{j} ight floor )

    令 ( g(i) = sumlimits_{j=1}^{i}leftlfloorfrac{i}{j} ight floor ) ,则 g 可以 ( nsqrt{n} ) 预处理。剩下的就是数论分块了。

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define ll long long
    using namespace std;
    const int N=5e4+5;
    int u[N],s[N],pri[N];bool vis[N];ll g[N];
    void init()
    {
      int lm=5e4,cnt=0;
      for(int t=1;t<=lm;t++)
        for(int i=1,j;i<=t;i=j+1)
          {
        int d=t/i; j=t/d;
        g[t]+=(ll)d*(j-i+1);
          }
      u[1]=s[1]=1;
      for(int i=2;i<=lm;i++)
        {
          if(!vis[i])pri[++cnt]=i,u[i]=-1;
          for(int j=1;j<=cnt&&(ll)i*pri[j]<=lm;j++)
        {
          vis[i*pri[j]]=1;
          if(i%pri[j]==0){u[i*pri[j]]=0;break;}
          u[i*pri[j]]=-u[i];
        }
          s[i]=s[i-1]+u[i];
        }
    }
    int main()
    {
      int T,n,m;scanf("%d",&T); init();
      while(T--)
        {
          scanf("%d%d",&n,&m);if(n>m)swap(n,m);
          ll ans=0;
          for(int i=1,j;i<=n;i=j+1)
        {
          int d0=n/i,d1=m/i; j=min(n/d0,m/d1);
          ans+=(ll)(s[j]-s[i-1])*g[d0]*g[d1];
        }
          printf("%lld
    ",ans);
        }
      return 0;
    }
  • 相关阅读:
    Python获取会议部分的信息内容(不断完善中)
    TensorFlow学习笔记(UTF-8 问题解决 UnicodeDecodeError: 'utf-8' codec can't decode byte 0xff in position 0: invalid start byte)
    Tensorflow学习笔记(对MNIST经典例程的)的代码注释与理解
    virtualenvwrapper
    最小二乘法与梯度下降的区别
    Git
    Jupyter
    Linux
    Iterm2
    Homebrew
  • 原文地址:https://www.cnblogs.com/Narh/p/10112476.html
Copyright © 2020-2023  润新知