• 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
  • 相关阅读:
    ssm整合用到的依赖jar包(不充足)
    eclipse中Maven web项目的目录结构浅析
    何时使用抽象类?何时使用接口?
    $().attr() 和 $().css的区别
    AJAX防重复提交的办法总结
    CentOS 8 扩展LVM,更改xfs卷报错解决方法
    安装Minikube无法访问k8s.gcr.io的简单解决办法
    Windows 10、Ubuntu 18.04 双系统 双硬盘 安装经验总结
    转眼十年
    Dresdon二次开发
  • 原文地址:https://www.cnblogs.com/Mr-ren/p/4227425.html
Copyright © 2020-2023  润新知