题意:

给出一个n行m列的点阵,求共有多少条非水平非竖直线至少经过其中两点。

UVa 1393 (容斥原理、GCD) Highways

分析:

首先说紫书上的思路,编程较简单且容易理解。由于对称性,所以只统计“\”这种线型的,最后乘2即是答案。

枚举斜线包围盒的大小,如果盒子的长宽ab互质,则是可以的。这种盒子共有(m-a)(n-b)个,但要减去其中重复的。如果有一个长宽为2a和2b的大盒子,则计数右下角的小盒子的同时,左上角的小盒子会重复,所以要减去重复的盒子的个数c = max(0, m-2a) * max(0, n-2b)

最后gcd(a, b)的值是要预处理的

 1 #include <cstdio>
 2 #include <algorithm>
 3 
 4 const int maxn = 300;
 5 int gcd[maxn+10][maxn+10];
 6 
 7 int GCD(int a, int b)
 8 {
 9     return b == 0 ? a : GCD(b, a%b);
10 }
11 
12 int main()
13 {
14     for(int i = 1; i <= maxn; ++i)
15         for(int j = 1; j <= i; ++j)
16             gcd[i][j] = gcd[j][i] = GCD(i, j);
17 
18     int n, m;
19     while(scanf("%d%d", &n, &m) == 2 && n)
20     {
21         int ans = 0;
22         for(int a = 1; a <= n; ++a)
23             for(int b = 1; b <= m; ++b)
24                 if(gcd[a][b] == 1)
25                 {
26                     int c = std::max(0, n-a*2) * std::max(0, m-b*2);
27                     ans += (n-a)*(m-b) - c;
28                 }
29 
30         printf("%d\n", ans * 2);
31     }
32 
33     return 0;
34 }
代码君

相关文章:

  • 2021-10-15
  • 2021-10-15
  • 2021-10-15
  • 2021-10-15
  • 2021-10-15
  • 2021-10-15
  • 2021-10-15
猜你喜欢
  • 2021-11-21
  • 2021-07-09
  • 2022-12-23
  • 2021-07-11
  • 2022-12-23
  • 2021-10-15
相关资源
相似解决方案