zoukankan      html  css  js  c++  java
  • BZOJ 3994 约数个数和

    莫比乌斯反演?不知道有没有用到。

    原式=∑(x=1...n)μ(x)∑(i=1..[n/x])d(i)∑(j=1..[m/x])d(j)。

    对miu,d分别前缀和,再对d*d进行分块。

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<cstring>
    #define maxn 50010
    using namespace std;
    long long miu[maxn],prime[maxn],e[maxn],k[maxn],pre[maxn],cnt=0,premiu[maxn];
    long long tk,n,m;
    bool vis[maxn];
    void get_prime()
    {
    memset(vis,false,sizeof(vis));
    e[1]=1;k[1]=1;miu[1]=1;
    for (long long i=2;i<=maxn-5;i++)
    {
    if (vis[i]==false)
    {
    prime[++cnt]=i;
    e[i]=1;k[i]=2;
    miu[i]=-1;
    }
    for (long long j=1;j<=cnt && i*prime[j]<=maxn-5;j++)
    {
    vis[i*prime[j]]=true;
    if (i%prime[j]==0)
    {
    k[i*prime[j]]=k[i]/(e[i]+1)*(e[i]+2);
    e[i*prime[j]]=e[i]+1;
    miu[i*prime[j]]=0;
    }
    else
    {
    k[i*prime[j]]=k[i]*k[prime[j]];
    e[i*prime[j]]=1;
    miu[i*prime[j]]=-miu[i];
    }
    }
    }
    pre[1]=k[1];premiu[1]=1;
    for (long long i=2;i<=maxn-5;i++)
    {
    pre[i]=pre[i-1]+k[i];
    premiu[i]=premiu[i-1]+miu[i];
    }
    }
    void work()
    {
    scanf("%lld%lld",&n,&m);
    if (n>m) swap(n,m);
    long long ans=0,r=1;
    while (r<=n)
    {
    long long j=min((n/(n/r)),(m/(m/r)));
    ans=ans+(premiu[j]-premiu[r-1])*pre[n/r]*pre[m/r];
    r=j+1;
    }
    printf("%lld ",ans);
    }
    int main()
    {
    scanf("%lld",&tk);
    get_prime();
    for (long long i=1;i<=tk;i++)
    work();
    return 0;
    }

  • 相关阅读:
    《DSP using MATLAB》Problem 6.17
    一些老物件
    《DSP using MATLAB》Problem 6.16
    《DSP using MATLAB》Problem 6.15
    《DSP using MATLAB》Problem 6.14
    《DSP using MATLAB》Problem 6.13
    《DSP using MATLAB》Problem 6.12
    《DSP using MATLAB》Problem 6.11
    P1414 又是毕业季II
    Trie树
  • 原文地址:https://www.cnblogs.com/ziliuziliu/p/5170140.html
Copyright © 2011-2022 走看看