《算法艺术与信息学竞赛》之 递推 例二 Yanghee 的算术 HDU - 2515

Problem Description
Yanghee 是一个小学生。他的数学老师给全班同学布置了一道家庭作业,即根据

一张不超过5000的n(n<50)个正整数组成的数表,两两相加得到n(n-1)/2个和,然后把它们排序。例如,如果数表含有四个数1,3,4,9,那么正确答案是4,5,7,10,12,13。Yanghee 做完作业以后和小伙伴们出去玩了一下午,回家以后发现老师给的数表不见了,可是他算出的答案还在。你能帮助Yanghee根据他的答案计算出原来的数表吗?

Input
输入第1行是1个正整数N,3<=n<50.然后有若干行,每行10个正整数,共计n(n-1)/2个数. 输入的数据有唯一解.

Output
按从小到大输出n个数x[1],x[2],…,x[n],每行1个,使得任意2个数之和恰是输入的n(n-1)/2个数.

Sample Input
15
3 4 5 6 7 8 9 10 11 12
13 14 15 16 5 6 7 8 9 10
11 12 13 14 15 16 17 7 8 9
10 11 12 13 14 15 16 17 18 9
10 11 12 13 14 15 16 17 18 19
11 12 13 14 15 16 17 18 19 20
13 14 15 16 17 18 19 20 21 15
16 17 18 19 20 21 22 17 18 19
20 21 22 23 19 20 21 22 23 24
21 22 23 24 25 23 24 25 26 25
26 27 27 28 29

Sample Output
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

这是一道非常经典的递推题,但是这个题目描述的我认为是有些问题的,题目上说将这些数进行排序,但是和样例输入中所给的情况是不一样的,个人感觉可能是出题人在造数据时进行了一些简化,经过我多次探索,发现其实对于这个输入中的数表根本不需要排序,直接做就可以Ac。
那么来说说本题的思路:首先找到最小的那个数,(我们假设原数表中最小的三个数分别为x,y,z,x小于y小于z)很明显,最小的那个数a[1]是等于x+y的,同理x+z=a[2],但是y+z就不一定=a[3]了,我们需要枚举来寻找答案,我们需要枚举3~n(n-1)/2吗?答案是否,因为y+z最大是不会超过a[n]的(这是因为比y+z要小的只可能是a[1]+a[k],当k取完2~n时,最小的就是a[2]+a[3]了),这样,本题的枚举范围就大大缩小了。
最后就很容易了,直接用a[1]~a[n-1]减去x即可得到所有的值(这是因为题目对于数据有所简化)。
对了,有一点要补充,在解方程是,我们是有如下简化方法的(应该是初中学的东西了)

x+y=a.....1
y+z=b.....2
x+z=c.....3
1+2+3得:2*(x+y+z)=a+b+c;
所以:x+y+z=(a+b+c)/2.....4
4-1可得z;
4-2可得x;
4-3可得y;
这些写法在代码中都有体现。

接下来上代码:

#include<bits/stdc++.h>
using namespace std;
int n,a[1500],b[55];
int main(){
    scanf("%d",&n);
    int m=(n*(n-1))/2;
    for(int i=1;i<=m;i++)
        scanf("%d",&a[i]);
    int x,y,z;
    for(int i=3;i<=n+1;i++){
        int sum=a[1]+a[2]+a[i];
        if(sum%2==1)continue;//因为要除以2 所以不是偶数无解 
        sum=sum/2;
        x=sum-a[3];
        y=sum-a[2];
        z=sum-a[1];
        //求解x,y,z 
        if(x>0&&y>0&&z>0)//找到解 
            break;
    }
    b[1]=x;
    b[2]=y;
    b[3]=z;
    for(int i=1;i<n;i++)
        b[i+1]=a[i]-x;//递推出其他解 
    for(int i=1;i<=n;i++)
        printf("%d\n",b[i]);//输出 
    return 0;
}

以上为个人见解,代码是原创,希望大家多多评论指正。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值