zoukankan      html  css  js  c++  java
  • bzoj2005 能量采集 莫比乌斯或者普通容斥

    /**
    题目:bzoj2005 能量采集 
    链接:https://vjudge.net/contest/178455#problem/F
    题意:栋栋有一块长方形的地,他在地上种了一种能量植物,这种植物可以采集太阳光的能量。在这些植物采集能量后,
    栋栋再使用一个能量汇集机器把这些植物采集到的能量汇集到一起。 栋栋的植物种得非常整齐,一共有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的能
    量损失。
    
    思路:
    等价于求sigma(gcd(x,y)*2-1)  (1<=x<=n,1<=y<=m);
    
    = sigma(gcd(x,y)*2)-n*m = 2*sigma(gcd(x,y)) - n*m = 2*sigma(k*gcd) - n*m;(k表示gcd出现的次数)
    
    数据范围小的时候:
    定义:
    f(n)表示gcd(x,y)==n的对数。
    F(n)表示n|gcd(x,y)的对数。  
    
    因为F(n)包含了gcd是n的倍数的值。所以要把他们减掉。 f(n) = F(n)-f(2*n)-f(3*n)-..-f(k*n); (k*n<=min(n,m)) 后面的n,m是数据范围.
    
    逆序处理即可,注意溢出!!!  
    
    
    数据范围大的时候:
    定义:
    f(n)表示gcd(x,y)==n的对数。
    F(n)表示n|gcd(x,y)的对数。
    
    枚举gcd==p,1<=p<=min(n,m);
    
    f(p) = sigma(mu[d/p]*F(d)) (p|d) 
        
    F(d) = (n/d)*(m/d);   
    
    f(p)表示gcd(x,y)==p的对数。x在[1,n],y在[1,m];等价于:求f(1)表示gcd(x,y)==1的对数。x在[1,n/p],y在[1,m/p]; 用除法的取值,预处理莫比乌斯前缀和。
    
    N*sqrt(N)复杂度。
    
    
    
    
    
    */
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <set>
    #include <iostream>
    #include <vector>
    #include <map>
    using namespace std;
    typedef long long LL;
    #define ms(x,y) memset(x,y,sizeof x)
    typedef pair<int, int> P;
    const LL INF = 1e10;
    const int mod = 1e9 + 7;
    const int maxn = 1e5 + 100;
    LL f[maxn], g[maxn];
    /*
    int prime[maxn], tot, not_prime[maxn];
    int mu[maxn], sum[maxn];
    void init()
    {
        mu[1] = 1;
        tot = 0;
        for(int i = 2; i < maxn; i++){
            if(!not_prime[i]){
                prime[++tot] = i;
                mu[i] = -1;
            }
            for(int j = 1; prime[j]*i<maxn; j++){
                not_prime[prime[j]*i] = 1;
                if(i%prime[j]==0){
                    mu[prime[j]*i] = 0;
                    break;
                }
                mu[prime[j]*i] = -mu[i];
            }
        }
        for(int i = 1; i < maxn; i++) sum[i] = sum[i-1]+mu[i];
    }
    LL solve(int n,int m)///x在[1,n], y在[1,m] gcd(x,y)=1的对数。
    {
        LL ans = 0;
        int last;
        for(int i = 1; i <= n; i=last+1){
            last = min(n/(n/i),m/(m/i));
            ans += (LL)(sum[last]-sum[i-1])*(n/i)*(m/i);
        }
        return ans;
    }*/
    int main()
    {
        //freopen("in.txt","r",stdin);
        int T;
        int n, m;
        //init();
        while(scanf("%d%d",&n,&m)==2)
        {
            if(n>m) swap(n,m);
            LL ans = 0;
            for(int i = n; i >= 1; i--){
                g[i] = (LL)(n/i)*(m/i);
                for(int j = i*2; j <= n; j+=i){
                    g[i] -= f[j];
                }
                f[i] = g[i];
                ans += i*f[i];
            }
    
            printf("%lld
    ",ans*2-(LL)n*m);///溢出了啊。
        }
        return 0;
    }
  • 相关阅读:
    优步中国大举扩张,2016进军100城市!
    优步中国:2月底前进军广东、湖南、湖北18个城市
    Uber能知道你是不是在开车的时候玩手机
    Uber入驻四川乐山峨眉地区
    南京优步上线黄金区域,接单可享更高奖励!
    优步UBER司机全国各地奖励政策汇总 (2月1日-2月7日)
    成都Uber优步司机奖励政策(2月1日)
    北京Uber优步司机奖励政策(2月1日)
    滴滴快车奖励政策,高峰奖励,翻倍奖励,按成交率,指派单数分级(2月1日)
    跨程序共享数据,读取联系人信息
  • 原文地址:https://www.cnblogs.com/xiaochaoqun/p/7363682.html
Copyright © 2011-2022 走看看