How Many Points of Intersection? ——求交点问题

  How Many Points of Intersection? 

We have two rows. There are a dots on the top row and b dots on the bottom row. We draw line segments connecting every dot on the top row with every dot on the bottom row. The dots are arranged in such a way that the number of internal intersections among the line segments is maximized. To achieve this goal we must not allow more than two line segments to intersect in a point. The intersection points on the top row and the bottom are not included in our count; we can allow more than two line segments to intersect on those two rows. Given the value of a and b, your task is to compute P(ab), the number of intersections in between the two rows. For example, in the following figure a = 2 and b = 3. This figure illustrates that P(2, 3) = 3.

\epsfbox{p10790.eps}

Input 

Each line in the input will contain two positive integers a ( 0 < a$ \le$20000) and b ( 0 < b$ \le$20000). Input is terminated by a line where both a and b are zero. This case should not be processed. You will need to process at most 1200 sets of inputs.

Output 

For each line of input, print in a line the serial of output followed by the value of P(ab). Look at the output for sample input for details. You can assume that the output for the test cases will fit in 64-bit signed integers.

Sample Input 

2 2
2 3
3 3
0 0

Sample Output 

Case 1: 1
Case 2: 3
Case 3: 9



题意:一直两条平行线,一条平行线上有n个点,另一条平行线上有m个点,将n个点分别与m个点相连,问有多少交点。

题解:如图所示:



假设有4,4个点,先将1点和a,b,c,d点相连,如图(1)所示,这时,没有一个交点。完成后,图中有4条线

连接2a,分别和1b,1c,1d相交,产生3个交点,连接2b,分别和1c,1d相交,产生两个交点,连接2c,和1d相交,产生一个交点,连接2d,没有相交线段,没有交点产生。这个过程,产生交点数为0 + 1 + 2 + 3,如图(2)所示。完成后,图中有8条线

连接3a,分别和1b,1c,1d,2b,2c,2d,相交,产生6个交点,连接3b,分别和1c,1d,2c,2d相交,产生4个交点,连接3c,分别和1d,2d相交,产生2个交点,连接3d,没有交线产生,没有交点。这个过程,产生交点数为0 + 2 + 4 + 6,如图(3)所示。完成后,图中有12条线

连接4a,分别和1b,1c,1d,2b,2c,2d,3b,3c,3d相交,产生9个交点,连接4b,分别和1c,1d,2c,2d,3c,3d相交,产生6个交点,连接4c,分别和1d,2d,3d相交,产生3个交点,连接4d,没有交点产生,整个过程,产生交点数为0 + 3 + 6 + 9,如图(4)所示。


根据上面示例,可以总结规律如下:

假设n,m个点,用n分别连接m个点。

第一次连接,没有交点产生

第二次连接,公差为1,产生交点数为1 + 2 + 3 + 4 + 5 + ...... + m - 1;

第三次连接,公差为2,产生交点数为2 + 4 + 6 + 8 + 10 + ...... + 2(m - 1);

第四次连接,公差为3,产生交点数为3 + 6 + 9 + 12 + 15 + ...... + 3(m - 1);

.......

第 n 次连接,公差为n - 1,产生交点数为(n - 1) + 2(n - 1) + 3(n - 1) + ...... + (m - 1)(n - 1);



还有一个更好理解的推理过程:

首先明白当1和a,b,c,d分别相连的时候没有交点产生,当2分别和a,b,c,d相连的时候假设有D个交点产生,此时图中共有2*m条连线,当3分别和a,b,c,d相连的时候,和1产生的交点为D,和2产生的交点为D,所以产生2D个交点,以此类推,当n与m个点相连的时候会产生(n-1)m个交点,所以推出公式:(n * (n - 1) * m * (m - 1))/4。


其实两种推理过程相似,如果将第一种推理过程中的每一个公差都提出来,则会发现剩下的部分都是从1到m-1的累加,而公差也是从1到n - 1的累加,两者相乘,得出上面的公式。



重点注意:变量一定都要用long long,不要以为n,m没有超出Int范围就用int,那样计算会产生错误。

一步一步累加的代码

#include <iostream>
#include <stdio.h>
#include <string.h>

using namespace std;

int main()
{
    int i,j,k;
    long long sum,num,n,m;
    k = 1;
    while(~scanf("%lld%lld",&n,&m))
    {
        if(n == 0 && m == 0)
            break;
        sum = 0;
        for(i = 1;i < n;i++)
        {
            num = (m - 1) * (i + i * (m - 1))/2;
            sum += num;
        }
        printf("Case %d: %lld\n",k++,sum);
    }
    return 0;
}


直接套公式的代码:

#include <iostream>
#include <stdio.h>
#include <string.h>

using namespace std;

int main()
{
    int i,j,k;
    long long sum,num,n,m;
    k = 1;
    while(~scanf("%lld%lld",&n,&m))
    {
        if(n == 0 && m == 0)
            break;
        sum = (n * (n - 1) * m * (m - 1))/4;
        printf("Case %d: %lld\n",k++,sum);
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值