UVa 12373 - Pair of Touching Circles

题目:给你一个n*m的矩形的空间,在里面放入,圆心和半径都是整数的2个相切圆。

            有多少种不同的方法,旋转后相同的认为是不同的。

分析:数论。两圆有一个最小的放置边界矩形,求出矩形的摆放个数即可。

            能够符合题目条件的只有两种情况:

            1.两圆的连心线与矩形的边界平行;

            2.两圆的连心线是斜边,但是是勾股数组中的斜边。

#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>

using namespace std;

typedef struct dnode
{
	int a,b,c;
	dnode( int A, int B, int C ) {a = A;b = B;c = C;}
	dnode(){}
}data;
data D[1000];

int maps[1005][1005];

int main()
{
	//打表计算勾股数组,共881个 
	int count = 0;
	D[count ++] = data( 3, 4, 5 );
	for ( int i = 10 ; i <= 1000 ; ++ i )
	for ( int j = 8 ; j < i ; ++ j )
	for ( int k = 5 ; k < j ; ++ k )
		if ( k*k + j*j == i*i ) {
			D[count].a = k;
			D[count].b = j;
			D[count].c = i;
			count ++;
		}
	//计算这些勾股数组组成的矩形 
	memset( maps, 0, sizeof(maps) );
	for ( int i = 0 ; i < count ; ++ i )
	for ( int j = 1 ; j < D[i].c ; ++ j ) {
		int W = max( D[i].a+D[i].c, (max(j,D[i].c-j))<<1 );
		int H = max( D[i].b+D[i].c, (max(j,D[i].c-j))<<1 );
		if ( W <= 1000 && H <= 1000 ) {
			maps[W][H] += 2;
			maps[H][W] += 2;
		}
	}
	
	int T,H,W;
	while ( scanf("%d",&T) != EOF )
	for ( int t = 1 ; t <= T ; ++ t ) {
		scanf("%d%d",&H,&W);
		long long sum = 0LL;
		for ( int h = 2 ; h <= H ; h += 2 )
		for ( int w = 2 ; w <= W ; w += 2 ) {
			if ( h < w && w < 2*h || w < h && h < 2*w )
				sum += (W-w+1)*(H-h+1)*2;
			if ( h == 2*w || w == 2*h )
				sum += (W-w+1)*(H-h+1);
		}
		for ( int h = 2 ; h <= H ; ++ h )
		for ( int w = 2 ; w <= W ; ++ w )
			sum += maps[h][w]*(W-w+1)*(H-h+1);
			
		printf("Case %d: %lld\n",t,sum);
	}
	return 0;
}

你可能感兴趣的:(UVa 12373 - Pair of Touching Circles)