zoukankan      html  css  js  c++  java
  • UVa 1393 Highways (动态规划)

    题目

    题目大意

    有一个(n)(m)列((1 ≤ n, m ≤ 300))的点阵, 问: 一共有多少条非水平非竖直的直线至少穿过其中两个点? 例如, (n = 2), (m = 4)时答案为(12), (n = m = 3)时答案为(14)

    题解

    一开始看到题目我立马想到了(SPOJ 104 Highways)(基尔霍夫矩阵-树定理), 然而本题跟这个定理完全没有关系。

    首先考虑如何判断是否形成一条之前没有出现过的直线, 如果它向量两坐标的最大公约数为(1)则没有出现过。我们考虑用(dp_{i j})表示表示向量((x, y))((x ≤ i), (y ≤ j))共有多少个((x, y) = 1)的, 递推式为:

    [dp_{i j} = dp_{i - 1 j} + dp_{i j - 1} - dp_{i - 1 j - 1} ((i, j) ≠ 1) ]

    [dp_{i j} = dp_{i - 1 j} + dp_{i j - 1} - dp_{i - 1 j - 1} + 1 ((i, j) = 1) ]

    接下来处理所有点, 到((i, j))时, 内部各点与他组成的向量范围都在({(x, y)|x∈[1, i), y∈[1, j), x, y∈N^*})内, 那么可以用(dp_{i - 1 j - 1})表示其中有多少与其互质, 再减去重复计算的((dp_{frac{i - 1}{2} frac{j - 1}{2}}))。为了方便我们将所有(i), (j)增加(1), 最后减(1)即可。

    代码

    #include <cstdio>
    long long ans[310][310], dp[310][310];
    int n, m;
    inline long long GreatestCommonDivisor(const long long&, const long long&);
    int main(int argc, char const *argv[]) {
      for (register long long i(1); i <= 300ll; ++i) {
        for (register long long j(1); j <= 300ll; ++j) {
          dp[i][j] = dp[i - 1][j] + dp[i][j - 1] - dp[i - 1][j - 1] + (GreatestCommonDivisor(i, j) == 1);
          ans[i][j] = ans[i - 1][j] + ans[i][j - 1] - ans[i - 1][j - 1] + dp[i][j] - dp[i >> 1][j >> 1];
        }
      }
      while (~scanf("%d %d", &n, &m) && (n || m)) {
        printf("%lld
    ", ans[n - 1][m - 1] << 1);
      }
      return 0;
    }
    inline long long GreatestCommonDivisor(const long long &a, const long long &b) {
      return b ? GreatestCommonDivisor(b, a % b) : a;
    }
    
    
  • 相关阅读:
    bzoj 1761: [Baltic2009]beetle 区间dp
    NOI冲刺计划
    bzoj 2107: Spoj2832 Find The Determinant III 辗转相除法
    bzoj 2482: [Spoj GSS2] Can you answer these queries II 线段树
    bzoj 1209: [HNOI2004]最佳包裹 三维凸包
    SCOI2015题解 && 考试小结
    bzoj 2806: [Ctsc2012]Cheat 后缀自动机DP
    考场上应该想到。。。。
    spoj LCS 后缀自动机
    BZOJ 1639: [Usaco2007 Mar]Monthly Expense 月度开支
  • 原文地址:https://www.cnblogs.com/forth/p/9726252.html
Copyright © 2011-2022 走看看