UVA 12373 Pair of Touching Circles
思路:(注意2个圆的半径可以不一样)
有2种情况:
1) 水平和竖直放。这种情况很简单,刚开始以为只有这种情况,但是样例5不对,后来知道还有一种情况。
2)斜线也可以放。只要满足勾股数就可以。现在的问题是怎样确定包含2个圆的矩形,可以通过枚举一个圆的半径
来确定。
代码如下:
1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<algorithm> 5 #include<cstring> 6 #include<set> 7 #include<vector> 8 #define ll long long 9 #define M 1000 10 #define inf 1e10 11 #define mod 1000000007 12 using namespace std; 13 int n,m,cnt; 14 struct node 15 { 16 int x,y,t; 17 }p[M]; 18 void init() 19 { 20 cnt=0; 21 for(int i=1;i<500;i++) 22 for(int j=i+1;j<500;j++){ 23 int k=i*i+j*j; 24 int t=(int)sqrt(1.0*k); 25 if(t>M) break; 26 if(k==t*t){ 27 p[cnt].x=i; 28 p[cnt].t=t; 29 p[cnt++].y=j; 30 } 31 } 32 } 33 ll cal(int a,int b) 34 { 35 int u=a+b; 36 int v=b; 37 ll ans=0,t=0; 38 if(u<=n&&v<=m) t=(n-u+1)*(m-v+1); 39 if(v<=n&&u<=m) t+=(m-u+1)*(n-v+1); 40 if(a!=b) t=2*t; 41 ans+=t; 42 return ans; 43 } 44 int main() 45 { 46 int i,j,k,c,t,ca=0; 47 init(); 48 scanf("%d",&t); 49 while(t--){ 50 scanf("%d%d",&n,&m); 51 ll ans=0; 52 for(i=2;i<=n||i<=m;i+=2){ 53 for(j=i;i+j<=n||i+j<=m;j+=2) 54 ans+=cal(i,j); 55 } 56 for(i=0;i<cnt;i++) 57 for(j=1;j<p[i].t;j++){ 58 int u=max(p[i].x+p[i].t,2*max(j,p[i].t-j)); 59 int v=max(p[i].y+p[i].t,2*max(j,p[i].t-j)); 60 ll tt=0; 61 if(u<=n&&v<=m) tt=(n-u+1)*(m-v+1); 62 if(u<=m&&v<=n) tt+=(m-u+1)*(n-v+1); 63 ans+=2*tt; 64 } 65 printf("Case %d: %lld\n",++ca,ans); 66 } 67 return 0; 68 }