zoukankan      html  css  js  c++  java
  • UVa 1393

    链接:

    https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=4139

    题意:

    有一个n行m列(1≤n,m≤300)的点阵,问:一共有多少条非水平非竖直的直线至少穿过其中两个点?

    分析:

    不难发现两个方向是对称的,所以只统计“”型的,然后乘以2。
    方法是枚举直线的包围盒大小a*b,然后计算出包围盒可以放的位置。
    首先,当gcd(a,b)>1时肯定重复了。其次,如果放置位置不够靠左,也不够靠上,则它和它“左上方”的包围盒也重复了。
    假定左上角坐标为(0,0),则对于左上角在(x,y)的包围盒,其“左上方”的包围盒的左上角为(x-a,y-b)。
    这个“左上角”合法的条件是x-a≥0且y-b≥0。包围盒本身不出界的条件是x+a≤m-1, y+b≤n-1,一共有(m-a)(n-b)个,
    而“左上方”有包围盒的情况,即a≤x≤m-a-1且b≤y≤n-b-1,有c = max(0, m-2a) * max(0, n-2b)种放法。
    相减得到:a*b的包围盒有(m-a)(n-b)-c种放法。

    代码:

     1 #include <cstdio>
     2 #include <algorithm>
     3 using namespace std;
     4 
     5 const int UP = 300 + 5;
     6 int g[UP][UP];
     7 
     8 int gcd(int a, int b) {
     9     return b == 0 ? a : gcd(b, a%b);
    10 }
    11 
    12 int main() {
    13     for(int r = 1; r < UP; r++)
    14         for(int c = 1; c < UP; c++) g[r][c] = gcd(r,c);
    15     int n, m;
    16     while(scanf("%d%d", &n, &m) && n) {
    17         int ans = 0;
    18         for(int a = 1; a <= n; a++) {
    19             for(int b = 1; b <= m; b++) {
    20                 if(g[a][b] != 1) continue;
    21                 ans += (n-a) * (m-b) - max(n-a-a,0) * max(m-b-b,0);
    22             }
    23         }
    24         printf("%d
    ", ans*2);
    25     }
    26     return 0;
    27 }
  • 相关阅读:
    大数据面经
    mysql复习(2)
    java容器
    内存管理
    垃圾收集
    输入/输出流
    排序算法的稳定性及其汇总
    java传值与传引用
    linux复习6
    linux复习5
  • 原文地址:https://www.cnblogs.com/hkxy125/p/9727181.html
Copyright © 2011-2022 走看看