zoukankan      html  css  js  c++  java
  • P1447 [NOI2010]能量采集 [容斥 / "欧拉反演"]

    能量采集


    Descriptionmathcal{Description}
    求解 2i=1Nj=1Mgcd(i,j)NM2*sum_{i=1}^{N}sum_{j=1}^{M}gcd(i,j)-N*M

    做这道题前可以先看看 仪仗队 .


    正解部分
    首先说一下为什么求解的是上方的式子,
    对一个点 (x,y)(x,y), 遮拦这个点的个数为 gcd(x,y)1gcd(x,y)-1, 又因为一个点的贡献为 2(gcd(x,y)1)+12(gcd(x,y)-1)+1, 所以可以得到上式 .

    重点为下方这个式子:
    i=1Nj=1Mgcd(i,j)sum_{i=1}^{N}sum_{j=1}^{M}gcd(i,j)

    解法 11:

    容斥原理

    考虑枚举dd, 统计有多少 (i,j)(i,j) 满足 gcd(i,j)=dgcd(i,j)=d,
    dd 为约数的点对数为 NdMdlfloorfrac{N}{d} floorlfloorfrac{M}{d} floor ,
    只需将 dd 不是最小公倍数的点对数减去就行了, 具体 容斥 过程见代码 .
    时间复杂度 O(NlogN)O(NlogN)

    #include<cstdio>
    #include<algorithm>
    #define reg register
    typedef long long ll;
    
    const int maxn = 100005;
    
    int N;
    int M;
    
    ll Ans;
    ll cnt[maxn];
    
    int main(){
            scanf("%d%d", &N, &M);
            for(reg int d = std::min(N, M); d >= 1; d --){
                    cnt[d] = (1ll*M/d) * 1ll*(N/d);
                    for(reg int j = 2; j*d <= std::min(N, M); j ++) cnt[d] -= cnt[j*d];
                    Ans += (d*2 - 1) * cnt[d];
            }
            printf("%lld
    ", Ans);
            return 0;
    }
    
    解法 22:

    欧拉反演

    存在这个等式
    dNφ(d)=Nsum_{d|N} varphi(d) = N

    如果不懂请点击 这里

    NN 换为 gcd(i,j)gcd(i, j), 原式变为
    i=1Nj=1Mdgcd(i,j)φ(d)sum_{i=1}^{N}sum_{j=1}^{M} sum_{d|gcd(i,j)} varphi(d)

    d=1Nφ(d)NdMdsum_{d=1}^{N} varphi(d) lfloorfrac{N}{d} floorlfloorfrac{M}{d} floor

    代码略 .


  • 相关阅读:
    if语法案例
    其他6-break,continue,exit,return区别
    其他5-6种产生随机数的方法
    其他4-shell脚本后台运行知识
    算法练习 第三周
    回顾MySQL基础
    jsp中使用jQuery获取窗口高度不正确的问题
    初学java 学生管理系统——v04版本 改用web
    web项目中跳转路径的使用
    tomcat部署项目的方式
  • 原文地址:https://www.cnblogs.com/zbr162/p/11822571.html
Copyright © 2011-2022 走看看