题目链接:http://lightoj.com/volume_showproblem.php?problem=1366
题意:给出一个矩形,在内部画两个圆A和B使得AB都完全在矩形内且AB相切且AB的圆心和半径都是整数。求有多少个这样的画法?
思路:总的来说,相切有两种情况:(1)水平或垂直方向相切。这个比较简单,枚举两个圆的直径,然后分水平垂直两种情况,计算较小的那个圆可以移动的范围,其实可以移动的范围是一个矩形;(2)斜着相切。这时候两个圆心的距离必然是一个勾股数。所以枚举勾股数,然后再枚举小圆的半径,这时候我们可以计算出两个圆在X和Y方向的跨度,也就是一个矩形。然后判断这个矩形在整个大矩形中有多少可以放置的位置,这里可以横着放和竖着放两种情况。注意,在一种矩形中,两个圆可以左上右下或者左下右上两种方式。然后两个圆半径不等时还可以再交换位置。
vector<int> a,b,c;
int cnt,n,m;
void init()
{
int i,j,k,t;
FOR1(i,1000) FOR(j,i,1000)
{
k=i*i+j*j;
t=sqrt(1.0*k);
if(t*t==k) a.pb(i),b.pb(j),c.pb(t);
else if((t-1)*(t-1)==k) a.pb(i),b.pb(j),c.pb(t-1);
else if((t+1)*(t+1)==k) a.pb(i),b.pb(j),c.pb(t+1);
}
cnt=SZ(a);
}
i64 cal()
{
if(n>m) swap(n,m);
i64 ans=0;
int i,j,x,y;
for(i=2;i<=n;i+=2) for(j=i;j<=m;j+=2)
{
x=m-j+1-i;
y=n-j+1;
if(x>0&&y>0)
{
ans+=x*y;
if(i!=j) ans+=x*y;
}
x=n-j+1-i;
y=m-j+1;
if(x>0&&y>0)
{
ans+=x*y;
if(i!=j) ans+=x*y;
}
}
int xx,yy;
for(i=0;i<cnt&&a[i]<=n;i++) for(j=1;j+j<=c[i]&&c[i]<=m;j++)
{
xx=max(a[i]+c[i],(c[i]-j)*2);
yy=max(b[i]+c[i],(c[i]-j)*2);
x=n+1-xx;
y=m+1-yy;
if(x>0&&y>0)
{
ans+=x*y*2;
if(j+j!=c[i]) ans+=x*y*2;
}
x=m+1-xx;
y=n+1-yy;
if(x>0&&y>0)
{
ans+=x*y*2;
if(j+j!=c[i]) ans+=x*y*2;
}
}
return ans;
}
int main()
{
init();
int num=0;
rush()
{
RD(n,m);
printf("Case %d: ",++num);
PR(cal());
}
}