zoukankan      html  css  js  c++  java
  • BZOJ2005:[Noi2010]能量采集——题解

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

    Description

    栋栋有一块长方形的地,他在地上种了一种能量植物,这种植物可以采集太阳光的能量。在这些植物采集能量后,
    栋栋再使用一个能量汇集机器把这些植物采集到的能量汇集到一起。 栋栋的植物种得非常整齐,一共有n列,每列
    有m棵,植物的横竖间距都一样,因此对于每一棵植物,栋栋可以用一个坐标(x, y)来表示,其中x的范围是1至n,
    表示是在第x列,y的范围是1至m,表示是在第x列的第y棵。 由于能量汇集机器较大,不便移动,栋栋将它放在了
    一个角上,坐标正好是(0, 0)。 能量汇集机器在汇集的过程中有一定的能量损失。如果一棵植物与能量汇集机器
    连接而成的线段上有k棵植物,则能量的损失为2k + 1。例如,当能量汇集机器收集坐标为(2, 4)的植物时,由于
    连接线段上存在一棵植物(1, 2),会产生3的能量损失。注意,如果一棵植物与能量汇集机器连接的线段上没有植
    物,则能量损失为1。现在要计算总的能量损失。 下面给出了一个能量采集的例子,其中n = 5,m = 4,一共有20
    棵植物,在每棵植物上标明了能量汇集机器收集它的能量时产生的能量损失。 在这个例子中,总共产生了36的能
    量损失。

    Input

    仅包含一行,为两个整数n和m。

    Output

    仅包含一个整数,表示总共产生的能量损失。

    Sample Input

    【样例输入1】
    5 4
    【样例输入2】
    3 4

    Sample Output

    【样例输出1】
    36
    【样例输出2】
    20

    ————————————————————————

    参考了http://blog.csdn.net/Clove_unique/article/details/51089272

    如果你做过POJ3090的话,应该能够想到,对于一个点(x,y),则其到原点之间就经过了gcd(x,y)-1个点。

    证明很显然:设t=gcd(x,y),x=at,y=bt,显然经过(a,b)(2a,2b)……(x,y),不算最后一个点,一共经过了t-1个点。

    带入我们的公式得到我们所要求的结果:2*(∑gcd(x,y))-m*n

    也就是变成了求∑gcd(x,y)的题。

    莫比乌斯反演一下得到phi(d)(d|gcd(x,y))

    又因为d|gcd(x,y)导出d|a&&d|b,可以有:

    n/d*m/d*phi(d)

    好的我们又做完了。

    #include<cstdio>
    #include<queue>
    #include<cctype>
    #include<cstring>
    #include<cmath>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    const int N=100010;
    ll phi[N],su[N],sum[N];
    bool he[N];
    void Euler(int n){
        int tot=0;
        phi[1]=1;    
        for(int i=2;i<=n;i++){    
        if(!he[i]){    
            su[++tot]=i;    
            phi[i]=i-1;
        }    
        for(int j=1;j<=tot;j++){    
            if(i*su[j]>=n)break;    
            he[i*su[j]]=1;   
            if(i%su[j]==0){    
            phi[i*su[j]]=phi[i]*su[j];break;    
            }    
            else phi[i*su[j]]=phi[i]*(su[j]-1);  
        }
        }
        for(int i=1;i<=n;i++)phi[i]+=phi[i-1];
        return;
    }    
    int main(){
        ll n,m,ans=0;
        scanf("%lld%lld",&n,&m);
        if(n>m)swap(n,m);
        Euler(n+1);
        for(ll i=1,j;i<=n;i=j+1){
        j=min(n/(n/i),m/(m/i));
        ans+=(ll)(phi[j]-phi[i-1])*(n/i)*(m/i);
        }
        printf("%lld
    ",2*ans-n*m);
        return 0;
    }
  • 相关阅读:
    容器跨主机网络通信学习笔记(以Flannel为例)
    Kubernetes控制器Job和CronJob
    记一次使用Flannel插件排错历程
    Kubernetes控制器Deployment
    Kubernetes如何通过StatefulSet支持有状态应用?
    react18 来了,我 get 到...
    gojs 实用高级用法
    vuecli3 vue2 保留 webpack 支持 vite 成功实践
    calibre 报错 This application failed to start because no Qt platform plugin could be initialized. Reinstalling the application may fix this problem. 解决
    unable to recognize "*.yaml": no matches for kind "RoleBinding" in version "rbac.authorization.k8s.io/v1beta1"
  • 原文地址:https://www.cnblogs.com/luyouqi233/p/8195385.html
Copyright © 2011-2022 走看看