zoukankan      html  css  js  c++  java
  • ACdream 1148(莫比乌斯反演+分块)

    传送门:GCD SUM

    题意:给出N,M
    执行如下程序:
    long long  ans = 0,ansx = 0,ansy = 0;
    for(int i = 1; i <= N; i ++)
       for(int j = 1; j <= M; j ++)
           if(gcd(i,j) == 1) ans ++,ansx += i,ansy += j;
    cout << ans << " " << ansx << " " << ansy << endl;

    分析:ans会莫比乌斯反演的人都能秒,ansx和ansy一样,需要推导一下,我们知道,在求ans时是这样推导的:

    设F(i)为[1,n][1,m]内gcd(x,y)==i的倍数时的总[x,y]数

    设f(i)为[1,n][1,m]内gcd(x,y)==i时的总[x,y]数

    F(i)=f(i)+f(2*i)+f(3*i)+……

    莫比乌斯反演得i:

    f(i)=μ(1)*F(i)+μ(2)*F(2*i)+μ(3)*F(3*i)+……

    f(1)=μ(1)*F(1)+μ(2)*F(2)+μ(3)*F(3)+……

    而F(i)=(m/i)*(n/i),直接代F(i)进去算即可。

    同样求ansx和ansy:

    定义A(i),gcd(a,b)=i时,加到ansx上的和

    定义B(i),gcd(a,b)=i,2*i,3*i……时,加到ansx上的总和

    B(i)=A(i)+A(2*i)+A(3*i)+……

    莫比乌斯反演得:

    A(i)=μ(1)*B(i)+μ(2)*B(2*i)+μ(3)*B(3*i)+……

    A(1)=μ(1)*B(1)+μ(2)*B(2)+μ(3)*B(3)+……

    B(i)=(n/i+1)*(n/i)/2*i * (m/i);直接代B(i)进去计算i即可。

    #pragma comment(linker,"/STACK:1024000000,1024000000")
    #include <cstdio>
    #include <cstring>
    #include <string>
    #include <cmath>
    #include <limits.h>
    #include <iostream>
    #include <algorithm>
    #include <queue>
    #include <cstdlib>
    #include <stack>
    #include <vector>
    #include <set>
    #include <map>
    #define LL long long
    #define mod 100000000
    #define inf 0x3f3f3f3f
    #define eps 1e-6
    #define N 100000
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    #define PII pair<int,int>
    using namespace std;
    inline int read()
    {
        char ch=getchar();int x=0,f=1;
        while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
        while(ch<='9'&&ch>='0'){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    bool vis[N+5];
    int mu[N+5],prime[N+5],sum[N+5],sumx[N+5];
    void Mobius()
    {
        memset(vis,false,sizeof(vis));
        mu[1]=1;
        int tot=0;
        for(int i=2;i<=N;i++)
        {
            if(!vis[i])
            {
                prime[tot++]=i;
                mu[i]=-1;
            }
            for(int j=0;j<tot;j++)
            {
                if(i*prime[j]>N)break;
                vis[i*prime[j]]=true;
                if(i%prime[j]==0)
                {
                    mu[i*prime[j]]=0;
                    break;
                }
                else
                {
                    mu[i*prime[j]]=-mu[i];
                }
            }
        }
        for(int i=1;i<=N;i++)sum[i]=sum[i-1]+mu[i],sumx[i]=sumx[i-1]+mu[i]*i;
    }
    int main()
    {
        int n,m;
        Mobius();
        while(scanf("%d%d",&n,&m)>0)
        {
            LL ans=0,ansx=0,ansy=0;
            for(int i=1,last=0;i<=min(n,m);i=last+1)
            {
                last=min(n/(n/i),m/(m/i));
                ans+=(LL)(sum[last]-sum[i-1])*(n/i)*(m/i);
                ansx+=(LL)(sumx[last]-sumx[i-1])*(n/i)*(n/i+1)/2*(m/i);
                ansy+=(LL)(sumx[last]-sumx[i-1])*(m/i)*(m/i+1)/2*(n/i);
            }
            printf("%lld %lld %lld
    ",ans,ansx,ansy);
        }
    }
    View Code
  • 相关阅读:
    文件编码转换
    mysql密码的奇怪问题
    python文件读写
    python中JSON的使用
    mysql默认字符编码的修改
    烧写uboot与linux操作系统,安装Samba,jlink驱动安装
    Busybox是什么?
    ubuntu 搭建GTK+以及glade2集成开发环境的一些方法
    Ubuntu linux安装ssh server
    UBoot启动过程(国嵌)
  • 原文地址:https://www.cnblogs.com/lienus/p/4296718.html
Copyright © 2011-2022 走看看