zoukankan      html  css  js  c++  java
  • uva 01393

    1393 - Highways

    Hackerland is a happy democratic country with m×n cities, arranged in a rectangular m by n grid and connected by m roads in the east-west direction and n roads in the north-south direction. By public demand, this orthogonal road system is to be supplemented by a system of highways in sucha way that there will be a direct connection between any pair of cities. Each highway is a straight line going through two or more cities. If two cities lie on the same highway, then they are directly connected.If two cities are in the same row or column, then they are already connected by the existing orthogonal road system (each east-west road connects all the m cities in that row and each north-south road connects all the n cities in that column), thus no new highway is needed to connect them. Your task is to count the number of highway that has to be built (a highway that goes through several cities on a straight line is counted as a single highway).

    epsfbox{p3720.eps}

    Input 

    The input contains several blocks of test cases. Each test case consists of a single line containing two integers 1$ le$n , m$ le$300 , specifying the number of cities. The input is terminated by a test case with n = m = 0 .

    Output 

    For each test case, output one line containing a single integer, the number of highways that must be built.

    Sample Input 

    2 4
    3 3
    0 0
    

    Sample Output 

    12
    14

    大意:

      给出一个 n*m 的网格,求出至少经过两个点的直线的总数.

    思路:

      最开始的思想是先全部算,然后再去重... 这个方法能做,但是不是最好的方法.

      先描述一下这个方法,枚举子矩形,然后计算出这样的直线能够放多少条, O(nm) 回答每个询问.

      更好的方法是预处理的递推.

      令 add[i][j] 为尺寸为 i,j 的长方形 (i, j) 顶点的贡献.

      那么 add[i][j] = add[i-1][j] + add[i][j-1] (1) - add[i-1][j-1] (2) + (gcd(i,j) == 1) (3).

      三个部分的含义分别是:

      add[i-1][j], add[i][j-1] 把上下的小一点的矩形贡献的直线向下(右) 平移一个单位依然为新的贡献.

      于是重复的部分就是 add[i-1][j-1] .

      当 i,j 坐标互质的时候, 一条新的线段产生.

      同理, 我们在计算 ans[i][j] 的时候, 要减掉 ans[i/2][j/2] 这是因为, ans[i/2][j/2] 的线段倍长之后全部都在 ans[i][j] 内.

      所以这个就快一些.

      

     1 #include<cstdlib>
     2 #include<cstdio>
     3 #include<iostream>
     4 using namespace std;
     5 const int maxn = 350;
     6 long long f[maxn][maxn],ans[maxn][maxn];
     7 int n,m;
     8 int gcd(int x,int y){
     9     return !y ? x : gcd(y,x%y);
    10 }
    11 void init(){
    12     for(int i = 1; i <= 310; ++i)
    13         for(int j = 1; j <= 310; ++j)
    14             f[i][j] = f[i][j-1] + f[i-1][j] - f[i-1][j-1] + (gcd(i,j) == 1);
    15     for(int i = 1; i <= 310; ++i)
    16         for(int j = 1; j <= 310; ++j)
    17             ans[i][j] = ans[i-1][j] + ans[i][j-1] - ans[i-1][j-1] + f[i][j] - f[i/2][j/2];
    18 }
    19 int main()
    20 {
    21     freopen("highway.in","r",stdin);
    22     freopen("highway.out","w",stdout);
    23     init();
    24     while(cin >> n >> m, n+m)
    25         cout << ans[n-1][m-1] * 2 << endl;
    26     return 0;
    27 }
    View Code
  • 相关阅读:
    如何将Sphinx生成的html文档集成进入Django
    npm提速
    Django缓存系统设置
    Django模板与Vue.js冲突问题
    CentOS7下安装配置MariaDB
    Linux下多线程下载利器 axel
    raspbian调整键盘设置
    git@github.com: Permission denied (publickey). fatal: Could not read from remote repository. Please make sure you have the correct access rights and the repository exists.
    彻底弄懂rem,px高度如何在不同的手机屏幕下自动换算
    PHP性能优化利器:生成器 yield理解(百万数据导出引申)
  • 原文地址:https://www.cnblogs.com/Mr-ren/p/4227425.html
Copyright © 2011-2022 走看看