zoukankan      html  css  js  c++  java
  • BZOJ_2820_YY的GCD_莫比乌斯反演

    BZOJ_2820_YY的GCD_莫比乌斯反演

    题意&分析:

    $sumlimits_pis[p]sumlimits_{i=1}^{n}sumlimits_{j=1}^{m}[gcd(i,j)=p]$

    $=sumlimits_pis[p]sumlimits_{i=1}^{lfloor frac{n}{p} floor}sumlimits_{j=1}^{lfloor frac{m}{p} floor}[gcd(i,j)=1]$

    $=sumlimits_pis[p]sumlimits_{i=1}^{lfloor frac{n}{p} floor}sumlimits_{j=1}^{lfloor frac{m}{p} floor}[gcd(i,j)=1]$

    $=sumlimits_pis[p]sumlimits_{i=1}^{lfloor frac{n}{p} floor}sumlimits_{j=1}^{lfloor frac{m}{p} floor}sumlimits_{d|gcd(i,j)}mu(d)$

    $=sumlimits_pis[p]sumlimits_{d=1}^{lfloor frac{n}{p} floor}mu(d)sumlimits_{i=1}^{lfloor frac{n}{dp} floor}sumlimits_{j=1}^{lfloor frac{m}{dp} floor}$

    $=sumlimits_{Q=1}^{n}lfloor frac{n}{Q} floorlfloorfrac{m}{Q} floorsumlimits_{p|Q}is[p]mu(lfloorfrac{Q}{p} floor)$

    $f(n)=sumlimits_{p|n}is[p]mu(lfloorfrac{n}{p} floor)$

    首先$f[i]$非积性,但可以通过μ处理,所以我们考虑线筛

    1.当$i$为质数时$f[i]=1$;

    2.当$i$%$p==0$时

    $f(i*p)=sumlimits_{d|i}is[d]mu(i*p/d)$

    当$d!=p$时$i*p/d$有两个以上的$p$,贡献为$0$,因此此时$f(i*p)=mu(i)$

    3.当$i$%$p!=0$时$i$与$p$互质

    $f(i*p)=sumlimits_{d|i}is[d]mu(i*p/d)+sumlimits_{d|p}is[d]mu(i*p/d)$
    $=f(i)*mu(p)+f(p)*mu(i)$
    $=mu(i)-f(i)$

    再记录下f[i]的前缀和,分块计算

    代码:

    #include <stdio.h>
    #include <string.h>
    #include <algorithm>
    using namespace std;
    #define LL long long
    int prime[4000010],vis[10000100],miu[10000100],f[10000100],sum[10000100],cnt;
    int T,n,m;
    inline void init()
    {
        miu[1]=1;
        for(int i=2;i<=10000000;i++)
        {
            if(!vis[i])
            {
                miu[i]=-1;
                f[i]=1;
                prime[++cnt]=i;    
            }
            for(int j=1;j<=cnt&&i*prime[j]<=10000000;j++)
            {
                vis[i*prime[j]]=1;
                if(i%prime[j]==0)
                {
                    miu[i*prime[j]]=0;
                    f[i*prime[j]]=miu[i];
                    break;
                }
                miu[i*prime[j]]=-miu[i];
                f[i*prime[j]]=miu[i]-f[i];
            }
            sum[i]=sum[i-1]+f[i];
        }
    }
    int main()
    {
        init();
        scanf("%d",&T);
        while(T--)
        {
            scanf("%d%d",&n,&m);
            if(n>m)swap(n,m);
            int lst;
            LL ans=0;
            for(int i=1;i<=n;i=lst+1)
            {
                lst=min(n/(n/i),m/(m/i));
                ans+=1ll*(sum[lst]-sum[i-1])*(n/i)*(m/i);
            }
            printf("%lld
    ",ans);
        }
    }
    
  • 相关阅读:
    合并两个排序的链表
    C#中调用C++的DLL文件
    C#获取进程的主窗口句柄
    在VS2008中编译纯c/c++程序并由c#调用过程 及 C++引用c#dll 模拟登陆实现
    C#多屏幕显示器编程
    Windows系统下的多显示器模式开发日记
    在 C# 中调用 C++
    C# 中调用C++ DLL (P/Invoke)
    C#多屏时控制窗体显示在哪个显示器上
    c# Winform 开发分屏显示应用程序
  • 原文地址:https://www.cnblogs.com/suika/p/8416704.html
Copyright © 2011-2022 走看看