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
  • 相关阅读:
    vivado 连接不上板子 There is no current hw_target
    excel 方框打钩
    2019新个税如何计算
    printf("loops %u / %u%c[K ", loops + 1, opts->loops, 27); printf("%cM", 27);
    HttpUtil
    Spring注入bean和aop的注意事项
    获取所有bean的名字
    不可见类有抽象父类,spring配置子类bean,注入父类,aop就可以切父类的方法
    实例/静态工厂方法得到bean
    注入抽象类的子类
  • 原文地址:https://www.cnblogs.com/Mr-ren/p/4227425.html
Copyright © 2011-2022 走看看