思路:给出一个矩形的宽w和高h,要在这个矩形中画两个圆,圆是外切的,且圆完全在矩形内部,圆心在整数点上面,两个的半径都是整数。求有多少种画法。
因为是相切的,所以两点之间的距离是其半径和,为整数。我们可以枚举两个圆A,B的相对位置,A在B的左下方,枚举的是B相对A的x,y值,x,y不同时为0。这样以来x <= h/2,y <= w/2。
这样之后就要求能装下这两个圆的最小矩形了(平行于坐标轴的)。看是否满足条件完全在大矩形内,最后求这个大矩形中有多少个小矩形。
有两种情况:
1:AB的圆心连线与坐标轴平行。
2:AB的圆心连线不与坐标轴平行。
主要是第二种情况,因为只枚举了B在A的右上方的情况,还有右下方没有枚举,但是又对称性可知,右上等于右下,乘2就是了。
// #pragma comment(linker, "/STACK:1024000000,1024000000") #include <iostream> #include <algorithm> #include <iomanip> #include <sstream> #include <string> #include <stack> #include <queue> #include <deque> #include <vector> #include <map> #include <set> #include <cstdio> #include <cstring> #include <cmath> #include <cstdlib> #include <climits> using namespace std; #define DEBUG #ifdef DEBUG #define debug(...) printf( __VA_ARGS__ ) #else #define debug(...) #endif #define CLR(x) memset(x, 0,sizeof x) #define MEM(x,y) memset(x, y,sizeof x) #define pk push_back template<class T> inline T Get_Max(const T&a,const T&b){return a < b?b:a;} template<class T> inline T Get_Min(const T&a,const T&b){return a < b?a:b;} typedef long long LL; typedef unsigned long long ULL; typedef pair<int,int> ii; const double eps = 1e-10; const int inf = 1 << 30; const int INF = 0x3f3f3f3f; const int MOD = 1e9 + 7; const int maxn = 1010; int GetDistance(int x,int y){ int m = (int)sqrt(x*x+y*y+0.1); if (m*m==x*x+y*y) return m; return 0; } int v[maxn][maxn]; inline void Init(){ for (int i = 0;i <= 500;++i) for (int j = 0;j <= 500;++j) v[i][j] = GetDistance(i,j); } int h,w; inline int In(int x,int y){ return (h-x+1)*(w-y+1); } inline void Solve(){ LL sum = 0; for (int i = 0;i <= h/2;++i){ for (int j = 0;j <= w/2;++j){ if (v[i][j]){ for (int k = 1;k < v[i][j];++k){ int y1 = Get_Min(-k,j-v[i][j]+k), y2 = Get_Max(k,j+v[i][j]-k); int x1 = Get_Min(-k,i-v[i][j]+k), x2 = Get_Max(k,i+v[i][j]-k); int x = x2 - x1; int y = y2 - y1; if (x>h || y>w) continue; int tmp = In(x,y); if (i>0&&j>0) tmp <<= 1; sum += 1LL*tmp; // debug("here\n"); } } } } cout << sum << endl; } int main() { // freopen("in.txt","r",stdin); // freopen("out.txt","w",stdout); int t, icase = 0; scanf("%d",&t); Init(); while(t--){ scanf("%d%d",&h,&w); printf("Case %d: ", ++icase); Solve(); } return 0; }