zoukankan      html  css  js  c++  java
  • [2019.1.14]BZOJ2005 [Noi2010]能量采集

    以下设(nge m)

    首先,一个点((x,y))((0,0))的路径上经过的点的数量(不包括首尾)为(gcd(x,y)-1)

    所以它的能量损耗为(2 imes gcd(x,y)-1)

    考虑如何统计(sum_{i=1}^nsum_{j=1}^m 2 imes gcd(i,j)-1)

    (f_x=sum_{i=1}^nsum_{j=1}^m[gcd(i,j)=x]),即(1le ile n,1le jle m)时,(gcd(i,j)=x)的数量。

    我们再记(F_x=sum_{x|i}f_i)

    莫名其妙想到了莫比乌斯反演,但是在这里显然不能用

    我们发现(F(x))其实就是满足(1le ile n,1le jle m,i|x,j|x)((i,j))数量,即(lfloorfrac{n}{x} floorlfloorfrac{m}{x} floor)

    我们还发现(f_i=F_i-sum_{x=2}^{lfloorfrac{n}{i} floor}f_{xi}),即(F_i)减去 (f_k)的和 ,其中(k)(i)的倍数且不等于(i)

    于是我们从大到小枚举(i)并计算(f_i),答案就是(sum_{i=1}^n(2 imes i-1) imes f_i)

    根据调和级数,其时间复杂度为(O(nlogn))

    code:

    #include<bits/stdc++.h>
    using namespace std;
    int n,m;
    long long num[100010],ans;
    int main(){
        scanf("%d%d",&n,&m),n<m?swap(n,m),0:0;
        for(int i=n;i>=1;--i){
            num[i]=1ll*(n/i)*(m/i);
            for(int j=i+i;j<=n;j+=i)num[i]-=num[j];
            ans+=(2*i-1)*num[i];
        }
        printf("%lld",ans);
        return 0;
    }
    
  • 相关阅读:
    C# 并行线程调用
    Oracle定时备份
    读取Excel里面的内容转为DataTable
    c# 将json数据转为键值对
    Py基础+中级
    深入理解DIP、IoC、DI以及IoC容器(转载)
    错误页面的配置
    JavaScript重载
    关于为空必填js判断
    MyEclipse CI 2018.8.0正式发布(附下载)
  • 原文地址:https://www.cnblogs.com/xryjr233/p/BZOJ2005.html
Copyright © 2011-2022 走看看