LA 3295 数三角形

https://vjudge.net/problem/UVALive-3295

题意:

数出n行m列的网格顶点能组成多少个三角形。

思路:

直接去数的话比较麻烦,这道题目是可以重复的,只要位置不同就可以了。

所有的情况就是,接下来剪去共线的情况。

①在同一行的共线,(n+1)×C(m+1,3)

②在同一列的共线,(m+1)×C(n+1,3)

③在斜线上的共线,gcd(i,j)-1表示起点(0,0)到终点(i,j)的共线情况,也就是说,此时已经确定了两个点。f(i,j)=f(i-1,j)+f(i,j-1)。

 1 #include<iostream>
 2 #include<algorithm>
 3 #include<cstring>
 4 #include<cstdio>
 5 #include<vector>
 6 #include<stack>
 7 #include<queue>
 8 #include<cmath>
 9 #include<map>
10 using namespace std;
11 
12 typedef long long LL;
13 const int maxn=1000+5;
14 
15 LL f[maxn][maxn];
16 
17 LL gcd(LL a,LL b)
18 {
19     return b==0?a:gcd(b,a%b);
20 }
21 
22 LL c(LL n, int m)
23 {
24     return n*(n-1)*(n-2)/6;
25 }
26 
27 void init()
28 {
29     for(int i=2;i<=1000;i++)
30     for(int j=2;j<=1000;j++)
31         f[i][j]=gcd(i,j)-1;
32 
33     for(int i=3;i<=1000;i++)
34     for(int j=2;j<=1000;j++)
35         f[i][j]+=f[i-1][j];
36 
37     for(int i=2;i<=1000;i++)
38     for(int j=3;j<=1000;j++)
39         f[i][j]+=f[i][j-1];
40 
41 
42     for(int i=2;i<=10;i++)
43     {
44         for(int j=2;j<=10;j++)
45             printf("f[%d][%d]: %d
",i,j,f[i][j]);
46     }
47 }
48 
49 int main()
50 {
51     //freopen("D:\input.txt","r",stdin);
52     int n,m;
53     int kase=0;
54     init();
55     while(~scanf("%d%d",&n,&m) && n && m)
56     {
57         n++, m++;
58         LL ans=c(n*m,3)-n*c(m,3)-m*c(n,3);
59         for(int i = 2; i < n; i ++)
60              for(int j = 2; j < m; j ++)
61                  ans -= 2*f[i][j];
62         printf("Case %d: %lld
",++kase,ans);
63     }
64     return 0;
65 }
原文地址:https://www.cnblogs.com/zyb993963526/p/6795746.html