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 }
View Code

 

 

 

你可能感兴趣的:(touch)