zoukankan      html  css  js  c++  java
  • [NOI2010]能量采集 解题报告

    [NOI2010]能量采集

    题目描述

    栋栋有一块长方形的地,他在地上种了一种能量植物,这种植物可以采集太阳光的能量。在这些植物采集能量后,栋栋再使用一个能量汇集机器把这些植物采集到的能量汇集到一起。

    栋栋的植物种得非常整齐,一共有(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)的能量损失。

    输入输出格式

    输入格式:

    仅包含一行,为两个整数(n)(m)

    输出格式:

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

    说明

    对于(10\%)的数据:(1 ≤ n, m ≤ 10)
    对于(50\%)的数据:(1 ≤ n, m ≤ 100)
    对于(80\%)的数据:(1 ≤ n, m ≤ 1000)
    对于(90\%)的数据:(1 ≤ n, m ≤ 10,000)
    对于(100\%)的数据:(1 ≤ n, m ≤ 100,000)


    题意:求

    [sum_{i=1}^nsum_{j=1}^m2 imes gcd(i,j)-1 ]

    直接暴力推式子了

    [sum_{i=1}^nsum_{j=1}^mgcd(i,j) ]

    [=sum_{k=1}^{min(n,m)}ksum_{i=1}^nsum_{j=1}^m[gcd(i,j)=k] ]

    (a=lfloorfrac{n}{k} floor,b=lfloorfrac{m}{k} floor)

    [=sum_{k=1}^{min(n,m)}ksum_{i=1}^asum_{j=1}^b[gcd(i,j)=1] ]

    [=sum_{k=1}^{min(n,m)}ksum_{i=1}^asum_{j=1}^bsum_{d|gcd(i,j)}mu(d) ]

    [=sum_{k=1}^{min(n,m)}ksum_{i=1}^asum_{j=1}^bsum_{d=1}^{min(i,j)}mu(d)[d|gcd(i,j)] ]

    [=sum_{k=1}^{min(n,m)}ksum_{d=1}^{min(a,b)}mu(d)sum_{i=1}^asum_{j=1}^b[d|gcd(i,j)] ]

    [=sum_{k=1}^{min(n,m)}ksum_{d=1}^{min(a,b)}mu(d)lfloorfrac{a}{d} floorlfloorfrac{b}{d} floor ]

    到这里虽然不够优,但是显然已经可以了。

    复杂度:(O(sumlimits_{i=1}^ni^{frac{1}{2}}))其实就是(O(nsqrt n))


    Code:

    #include <cstdio>
    #define ll long long
    const int N=1e5;
    ll ans=0;
    int mu[N+10],pri[N+10],ispri[N+10],cnt;
    void init()
    {
        for(int i=2;i<=N;i++)
        {
            if(!ispri[i])
            {
                mu[i]=-1;
                pri[++cnt]=i;
            }
            for(int j=1;j<=cnt&&pri[j]*i<=N;j++)
            {
                ispri[i*pri[j]]=1;
                if(i%pri[j]==0) break;
                else mu[i*pri[j]]=-mu[i];
            }
        }
        mu[1]=1;
        for(int i=2;i<=N;i++) mu[i]+=mu[i-1];
    }
    int n,m;
    int min(int x,int y){return x<y?x:y;}
    int main()
    {
        init();
        scanf("%d%d",&n,&m);
        for(int k=1;k<=min(n,m);k++)
        {
            int a=n/k,b=m/k;
            ll sum=0;
            for(int l=1,r;l<=min(a,b);l=r+1)
            {
                r=min(a/(a/l),b/(b/l));
                sum+=1ll*(mu[r]-mu[l-1])*(a/l)*(b/l);
            }
            ans+=sum*k;
        }
        printf("%lld
    ",ans*2ll-1ll*n*m);
        return 0;
    }
    

    2018.10.21

  • 相关阅读:
    【bzoj1176】[Balkan2007]Mokia
    【bzoj1503】[NOI2004]郁闷的出纳员
    C#设置和获取系统环境变量
    结伙创业指南及翻脸法则
    Unity3D_(游戏)卡牌03_选关界面
    Unity3D_(游戏)卡牌02_主菜单界面
    Unity3D_(游戏)卡牌01_启动屏界面
    Unity3D_(游戏)跳一跳超简单制作过程
    如何将项目托管到Github上
    Android_(游戏)打飞机06:后续
  • 原文地址:https://www.cnblogs.com/butterflydew/p/9824911.html
Copyright © 2011-2022 走看看