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 }