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

    【传送门:BZOJ2005


    简要题意:

      给出n*m个格子,位置从(1,1)到(n,m)

      在(0,0)的位置上有一个机器,如果(x,y)这个点与(0,0)的连线上覆盖了k个点(不包括(0,0)和(x,y)),则这个点的代价为2*k+1

      求出所有n*m个点的代价和


    题解:

      莫比乌斯反演

      显然代价和等于$sum_{x=1}^{n}sum_{y=1}^{m}2*gcd(x,y)-1$,可以转化为$-n*m+2*sum_{x=1}^{n}sum_{y=1}^{m}gcd(x,y)$

      那么我们只要求出$sum_{x=1}^{n}sum_{y=1}^{m}gcd(x,y)$就可以了

      因为一个数的所有因子的欧拉函数之和等于这个数

      所以转化为$$sum_{x=1}^{n}sum_{y=1}^{m}sum_{d=1}^{n}[d|x且d|y]phi(d)$$

      交换和式得到$$sum_{d=1}^{n}sum_{x=1}^{n}[d|x]sum_{y=1}^{m}[d|y]phi(d)$$

      实际上就等于$sum_{d=1}^{n}frac{n}{d}*frac{m}{d}*phi(d)$

      预处理欧拉函数就可以了


    参考代码:

    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    typedef long long LL;
    int prime[110000],v[110000];
    LL phi[110000];
    void pre(int n)
    {
        memset(v,0,sizeof(v));
        int m=0;phi[1]=1;
        for(int i=2;i<=n;i++)
        {
            if(v[i]==0)
            {
                v[i]=i;
                prime[++m]=i;
                phi[i]=i-1;
            }
            for(int j=1;j<=m;j++)
            {
                if(prime[j]>n/i||prime[j]>v[i]) break;
                v[prime[j]*i]=prime[j];
                if(i%prime[j]==0) phi[i*prime[j]]=phi[i]*prime[j];
                else phi[i*prime[j]]=phi[i]*(prime[j]-1);
            }
        }
    }
    int main()
    {
        pre(100000);
        int n,m;
        scanf("%d%d",&n,&m);
        LL ans=0;
        for(int i=1;i<=min(n,m);i++) ans+=(LL)(n/i)*(m/i)*phi[i];
        printf("%lld
    ",2*ans-(LL)n*m);
        return 0;
    }

     

  • 相关阅读:
    Alpha阶段第三次Scrum Meeting
    Alpha阶段第二次Scrum Meeting
    OverWatch团队文档格式规范
    Alpha阶段第一次Scrum Meeting
    BUAA_OVERWATCH第一次行动前战略部署
    【团队项目选题】自选项目:桌游APP
    团队博客作业- Week3
    龙威零式_团队项目例会记录_9
    龙威零式_团队项目例会记录_8
    数据获取以及处理系统 --- 技术规格说明书
  • 原文地址:https://www.cnblogs.com/Never-mind/p/9842045.html
Copyright © 2011-2022 走看看