solution of POJ:3187.Backward Digit Sums

3187.Backward Digit Sums

Description

FJ and his cows enjoy playing a mental game. They write down the numbers from 1 to N (1 <= N <= 10) in a certain order and then sum adjacent numbers to produce a new list with one fewer number. They repeat this until only a single number is left. For example, one instance of the game (when N=4) might go like this:

3   1   2   4

  4   3   6

    7   9

     16

Behind FJ’s back, the cows have started playing a more difficult game, in which they try to determine the starting sequence from only the final total and the number N. Unfortunately, the game is a bit above FJ’s mental arithmetic capabilities.

Write a program to help FJ play the game and keep up with the cows.

Input

Line 1: Two space-separated integers: N and the final sum.

Output

Line 1: An ordering of the integers 1..N that leads to the given sum. If there are multiple solutions, choose the one that is lexicographically least, i.e., that puts smaller numbers first.

Sample Input

4 16

Sample Output

3 1 2 4


结题思路 :
题意要求我们找到字典序最小的可行解。
要求1:杨辉三角的形式进行数据逐行的累加;
要点2:根据题意,实际上将杨辉三角进行倒转以后,三角中的每个数就代表题目中这个数被累加的次数;
要求3:暴力求解,利用杨辉三角的法则直接计算每个数最后被累加的次数。

杨辉三角第n层第k个数记为:(PS 我们的第一个是从0开始计数的哟)

Ckn=n!k!(nk)!=n(n1)(nk+1)k!

这里写图片描述

程序步骤:
第一步、首先构建字典序最小的一组解。
第二步、通过累加每个数被累加的和来判断这组解的可行性。
第三步、找到可行数组直接终止循环输出解。

具体程序(AC)如下:

#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
//这个位置的数被累加的次数
int count(int n, int k)
{
    int result = 1;
    for(int i = 0; i < k; ++i)
        result = result * (n - i) / (i + 1);
    return result;
}
int main()
{
    int n, result;
    cin>>n >>result;
    vector<int> listVal(n);
    for(int i = 0; i < n; ++i)
        listVal[i] = i + 1;
    int final;
    do{
        final = 0;
        for(int i = 0; i < n; ++i)
            final += listVal[i] * count(n - 1, i);
        if(final == result)//找到优解
        {
            if(n > 0)
                cout<<listVal[0];
            for(int i = 1; i < n; ++i)
                cout<<" "<<listVal[i];
            cout<<endl;
            break;
        }   
    }while(next_permutation(listVal.begin(), listVal.end()));
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值