2.梅花桩

  (blossom.pas/c/cpp)

【问题描述】

    小x在练习一门轻功,这门轻功是在梅花桩上跳来跳去,这门轻功是严格按照直线从一个梅花桩直接跳到另外一个梅花桩上。因为小x有恐高症,所以除了开始和结束的两个梅花桩,这条直线上不能有其他梅花桩,否则小x会真气中断,直接掉下来。

    小x的梅花桩有W+1行,H+1列,每个梅花桩之间距离都是1米,严格按照上下左右排列,小x的轻功最少能跳L1米,最多能跳L2米。

    作为一位爱思考的数学青年,小x想到了一个问题:有多少对梅花桩对小x来说是安全的,或者说有多少对梅花桩能保证小x练习这门轻功。

例如如下的地图:

W = 2  H = 1

**

**

**

而小x跳跃的长度为2和3之间。

这个梅花桩共有 (2+1) * (1+1) = 6个点以及有15 种配对方法

    (0,0)-(0,1)   (0,0)-(2,1)   (0,1)-(2,1)   (1,1)-(2,0)

    (0,0)-(1,0)   (0,1)-(1,0)   (1,0)-(1,1)   (1,1)-(2,1)

    (0,0)-(1,1)   (0,1)-(1,1)   (1,0)-(2,0)   (2,0)-(2,1)

    (0,0)-(2,0)   (0,1)-(2,0)   (1,0)-(2,1)

在这之中,只有四种是可以满足小x跳跃长度的

         始位  末位 长度          始位  末位 长度

        (0,0)-(2,0) 2.00             (0,1)-(2,0) 2.24

        (0,0)-(2,1) 2.24             (0,1)-(2,1) 2.00

但在这四种之中,(0,0)-(2,0)和(0,1)-(2,1)都不符合直线上没有其他梅花桩的要求,所以这个样例中只有2种结果。

【输入】

一行,4个整数W, H, L1, 和 L2

【输出】

一行。可能的方案数。

 

【输入输出样例】

blossom.in

blossom.out

2 1 2 3

2

 

【数据范围】

   50%数据 0<w,h,L1,L2<=100

   100% 数据  1 <= L1 <= L2 <= 1,500  1 <= W <= 1,000; 1 <= H <= 1,000

 

思路:

50%的分很好拿(四重循环)。

但是如何拿满分?(这个问题好)HOW

首先,如果L1<=1时,所有相邻为一的点都满足要求。

if(l1<=1)
    ans=ans+w*(h+1)+h*(w+1);

 

显然,当w=3,h=3时有(w+1)*h+h*(w+1);

然后,就枚举(x,y)到(0,0)的距离。如果小于L2,大于L1则算出有多少那样的矩形*2.

ans+=(w+1-x)*(h+1-y)

 

 

cpp:

 1 #include<iostream>
 2 #include<string>
 3 #include<ctime>
 4 #include<cstdio>
 5 #include<cstdlib>
 6 #include<cmath>
 7 #include<cstring>
 8 #include<algorithm>
 9 #include<queue>
10 #include<iomanip>
11 using namespace std;
12 const int maxn=5000001;
13 int w,h,l1,l2;
14 long long ans=0;
15 int gcd(int a,int b)
16 {
17     return b==0?a:gcd(b,a%b);
18 }
19 
20 int main()
21 {
22     freopen("blossom.in","r",stdin);
23     freopen("blossom.out","w",stdout);
24     ios::sync_with_stdio(false);
25     cin>>w>>h>>l1>>l2;
26     if(l1<=1)
27         ans=ans+w*(h+1)+h*(w+1);
28     for(int i=1;i<=w;i++)
29     {
30         for(int j=1;j<=h;j++)
31         {
32             int x=i*i+j*j;
33             if(x>=l1*l1&&x<=l2*l2)
34             {
35                 x=gcd(i,j);
36                 if(x==1)
37                 {
38                     ans=ans+(w-i+1)*(h-j+1)*2;
39                 }
40             }
41         }
42     }
43     cout<<ans<<endl;
44     return 0;
45 }
View Code