zoukankan      html  css  js  c++  java
  • BZOJ 2005 [Noi2010]能量采集

    2005: [Noi2010]能量采集

    Description

    栋栋有一块长方形的地,他在地上种了一种能量植物,这种植物可以采集太阳光的能量。在这些植物采集能量后,栋栋再使用一个能量汇集机器把这些植物采集到的能量汇集到一起。 栋栋的植物种得非常整齐,一共有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的能量损失。

    Input

    仅包含一行,为两个整数n和m。

    Output

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

    Sample Input

    【样例输入1】
    5 4
    【样例输入2】
    3 4

    Sample Output

    【样例输出1】
    36
    【样例输出2】
    20
    对于100%的数据:1 ≤ n, m ≤ 100,000

      我们本来只打算讲一个晚上的数论,但是时间并不够。后来,又讲了一个上午,然而并没有讲完。于是下午再讲,基本上已无人再听。
      身心俱疲。课件在这里
      这道题要求一个n*m的矩阵中各整点与(0,0)连线上的整点总数。
    BZOJ 3505 [Cqoi2014]数三角形中推得,(x,y)与(0,0)上有k=gcd(x,y)-1个整点。而此处要求∑∑k*2+1=∑∑gcd(i,j)*2-1
      这道题:∑∑gcd(i,j)=∑∑∑[d|i][d|j]phi(d)=∑(n/d)(m/d)phi(d)
      因为:n=∑phi(d)。
      明显先用欧拉筛,算出phi的前缀和。再分块,一个块中(n/i)(m/i)都相等。所以是O(n)预处理,O(sqrt(n))的单次询问(当然O(n)亦可)。
      但是我们也可以使用容斥原理,算出∑∑gcd(i,j)。复杂度是O(nlg n)的。
      代码如下(调了很久……前缀和导致的变化,long long的取值):
     1 /**************************************************************
     2     Problem: 2005
     3     User: Doggu
     4     Language: C++
     5     Result: Accepted
     6     Time:4 ms
     7     Memory:2092 kb
     8 ****************************************************************/
     9  
    10 #include <cstdio>
    11 #include <algorithm>
    12 const int N = 100100;
    13 int n, m, prime[N], ptot;
    14 long long phi[N], ans;
    15 bool vis[N];
    16 void EULER(int n) {
    17     phi[1]=1;
    18     for( int i = 2; i <= n; i++ ) {
    19         if(!vis[i]) prime[++ptot]=i, phi[i]=i-1;
    20         for( int j = 1; j <= ptot; j++ ) {
    21             if((long long)i*prime[j]>n) break;
    22             vis[i*prime[j]]=1;
    23             phi[i*prime[j]]=phi[i]*(prime[j]-1);
    24             if(i%prime[j]==0) {
    25                 phi[i*prime[j]]=phi[i]*prime[j];
    26                 break;
    27             }
    28         }
    29         phi[i]+=phi[i-1];
    30     }
    31 }
    32 int main() {
    33     scanf("%d%d",&n,&m);
    34     if(n>m) std::swap(n,m);
    35     EULER(n);
    36     for( int a = 1, ed; a <= n; a=ed+1 ) {
    37         ed=std::min(n/(n/a),m/(m/a));
    38         ans+=(long long)(phi[ed]-phi[a-1])*(n/a)*(m/a);
    39     }
    40     printf("%lld
    ",ans*2-(long long)n*m);
    41     return 0;
    42 }
    狄利克雷卷积+欧拉筛+分块
  • 相关阅读:
    用R语言实现对不平衡数据的四种处理方法
    用R语言实现对不平衡数据的四种处理方法
    Java学习——Applet画8个同心圆
    Java学习——Applet画8个同心圆
    Java学习——Applet写字符串(调字体)
    Java学习——Applet写字符串(调字体)
    ZOJ 2913 Bus Pass (近期的最远BFS HDU2377)
    机房结账功能分析
    数据结构记录--排序
    C#创建PDF文档
  • 原文地址:https://www.cnblogs.com/Doggu/p/bzoj2005.html
Copyright © 2011-2022 走看看