• ●BZOJ 2005 NOI 2010 能量采集


    题链:

    http://www.lydsy.com/JudgeOnline/problem.php?id=2005

    题解:

    一个带有容斥思想的递推。
    %%%
    首先,对于一个点 (x,y) 在路径 (0,0)->(x,y)上,经过的点数为 GCD(x,y)-1
    所以改点的贡献为 2*GCD(x,y)-1
                N    M
    那么,ANS = ∑    ∑(2*GCD(i,j)-1)
               i=1 j=1
    显然超时。
    考虑到 GCD<=100000,
    那么是否可以求出 f[i] 表示 GCD==i的点对 (x,y)有多少个。
    然后用f[i]去得出答案 (ans+=f[i]*(2*i-1))?
     
    接下来就是神奇的递推了。
    f[i]=(N/i)*(M/i) - f[i*k]  (i*k<=min(N,M))
    上式中 (N/i)*(M/i) 求得的是 有i这个公约数的点对(x,y)的个数
    因为这些点对的最大公约数GCD可能为 i,2i,3i......
    所以减掉f[2i],f[3i],f[4i]......就得到了f[i].

    代码:

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #define ll long long
    using namespace std;
    ll f[100005];
    ll N,M,K,ans;
    int main()
    {
    	freopen("energy.in","r",stdin);
    	freopen("energy.out","w",stdout);
    	cin>>N>>M; K=min(N,M);
    	for(int i=K;i>=1;i--){
    		f[i]=(N/i)*(M/i);
    		for(int j=2;i*j<=K;j++)
    			f[i]-=f[i*j];
    		ans+=f[i]*(2*i-1);
    	}
    	printf("%lld",ans);
    	return 0;
    }
    

      

    2.Möbius inversion formula

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #define MAXN 100500
    using namespace std;
    int mu[MAXN],pmu[MAXN];
    void Sieve(){
        static bool np[MAXN];
        static int prime[MAXN],pnt;
        mu[1]=pmu[1]=1;
        for(int i=2;i<=100000;i++){
            if(!np[i]) prime[++pnt]=i,mu[i]=-1;
            for(int j=1;j<=pnt&&i<=100000/prime[j];j++){
                np[i*prime[j]]=1;
                if(i%prime[j]) mu[i*prime[j]]=-mu[i];
                else break;
            }
            pmu[i]=pmu[i-1]+mu[i];
        }
    }
    long long f(int n,int m){
        long long ret=0; int mini=min(n,m);
        for(int i=1,last;i<=mini;i=last+1){
            last=min(n/(n/i),m/(m/i));
            ret+=1ll*(pmu[last]-pmu[i-1])*(n/i)*(m/i);
        }
        return ret;
    }
    int main(){
        Sieve();
        int n,m,mini; long long ans=0;
        scanf("%d%d",&n,&m); mini=min(n,m);
        for(int g=1;g<=mini;g++)
    	ans+=(2*g-1)*f(n/g,m/g);
        printf("%lld
    ",ans);  
        return 0;
    }
    

      

  • 相关阅读:
    jquery事件优化---事件委托
    2017年7月6号,总结所遇到的问题
    js日期函数
    跨域请求所遇到的错误
    ajax设置Access-Control-Allow-Origin实现跨域访问
    php提前输出响应及注意问题
    php中的日期和时间
    跨域请求json数据
    C++ 与 Visual Studio 2019 和 WSL(四)——库组件
    fpic 和 fPIC
  • 原文地址:https://www.cnblogs.com/zj75211/p/7944189.html
Copyright © 2020-2023  润新知