Enum:Backward Digit Sums(POJ 3187)

                  

                 反过来推

  题目大意:就是农夫和这只牛又杠上了(怎么老是牛啊,能换点花样吗),给出一行数(从1到N),按杨辉三角的形式叠加到最后,可以得到一个数,现在反过来问你,如果我给你这个数,你找出一开始的序列(可能存在多个序列,输出字典序最小的那个)。

  这一题首先你要看懂原文的那个1到N是什么意思,就是那一行数只能是1到N,而不是1到10(我一开始犯了这个愚蠢的错误,导致枚举到风扇呼呼的转),如果是这样给你,那么这道题就很简单啦,就直接是用next_permutation枚举所有的序列就可以了,然后找出字典序最小的那个。

  但是这里有个问题,如果你真的找出一个然后去比较字典序,那真是太慢了,一开始直接暴力枚举+测试一个一个字串的速度

  

  看到了没?差点就超时了,这个还是我直接用二维数组+迭代的,换暴力DFS直接就超时了吧。

  其实这个时候我们可以看到,这样做我们忽略了一个事实,如果字串是顺序的,我们可以回想一下我们的枚举是怎枚举的(STL里面也是这么写的),是一个循环从1到N,然后找到没有被标记的数,然后进去递归,这样的话,其实就隐含了字典序排序了,如果我们一开始按照12345678...这样排列下来,那么找到的第一个字串,肯定是字典序最小的,所以,我们找到之后直接break就可以了

  

 1 #include <iostream>
 2 #include <functional>
 3 #include <algorithm>
 4
 5 using namespace std;
 6
 7 static int set[11], tmp[11];
 8 static int sum, length;
 9
10 void enum_string(const int,const int);
11 bool scmop(void);
12
13 int main(void)
14 {
15     while (~scanf("%d%d", &length, &sum))
16     {
17         for (int i = 1; i <= length; i++)
18             tmp[i - 1] = i;
19         if (length == 1 && tmp[0] == sum)
20         {
21             for (int i = 0; i < length; i++)
22                 printf("%d ", tmp[i]);
23             printf("\n");
24             continue;
25         }
26         do{
27             for (int i = 0; i < length - 1; i++)
28                 set[i] = tmp[i] + tmp[i + 1];
29             for (int i = length - 2; i >= 0; i--)
30             {
31                 for (int j = 0; j < i; j++)
32                     set[j] = set[j] + set[j + 1];
33             }
34             if (set[0] == sum)
35             {
36                 for (int i = 0; i < length; i++)
37                     printf("%d ", tmp[i]);
38                 printf("\n");
39                 break;
40             }
41         } while (next_permutation(tmp, tmp + length));
42
43     }
44     return 0;
45 }

    

  还没完,开始我不是说了吗?这一题是按照杨辉三角的形式展开的,我们知道杨辉三角的每一行的数都是组合数Ckn,那么在数学上,杨辉三角的加法一行数的相加次数相当于这个Ckn,

    

    也就是说,我们只用把这一行的数乘以Ckn就可以得到结果了,这样做会更快

  

#include <iostream>
#include <functional>
#include <algorithm>

using namespace std;

static int set_sum, tmp[11], Cn[11];
static int sum, length;

void enum_string(const int, const int);
bool scmop(void);
void Cal_Cn(const int);

int main(void)
{
    while (~scanf("%d%d", &length, &sum))
    {
        for (int i = 1; i <= length; i++)
            tmp[i - 1] = i;
        memset(Cn, 0, sizeof(Cn));
        Cal_Cn(length);
        if (length == 1 && tmp[0] == sum)
        {
            for (int i = 0; i < length; i++)
                printf("%d ", tmp[i]);
            printf("\n");
            continue;
        }
        do{
            set_sum = 0;
            for (int i = 0; i < length; i++)
                set_sum += Cn[i] * tmp[i];
            if (set_sum == sum)
            {
                for (int i = 0; i < length; i++)
                    printf("%d ", tmp[i]);
                printf("\n");
                break;
            }
        } while (next_permutation(tmp, tmp + length));
    }
    return 0;
}

void Cal_Cn(const int length)
{
    Cn[0] = 1;
    for (int j = 1; j < length; j++)
    {
        Cn[j] = length - 1;
        for (int k = 2; k <= j; k++)
            Cn[j] *= (length - k);
        for (int k = 1; k <= j; k++)
            Cn[j] /= k;
    }
}

  

  最后,32ms

时间: 2024-10-23 21:00:03

Enum:Backward Digit Sums(POJ 3187)的相关文章

POJ 3187 Backward Digit Sums(next_permutation)

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

【POJ - 3187】Backward Digit Sums(搜索)

-->Backward Digit Sums 直接写中文了 Descriptions: FJ 和 他的奶牛们在玩一个心理游戏.他们以某种方式写下1至N的数字(1<=N<=10). 然后把相邻的数相加的到新的一行数.重复这一操作直至只剩一个数字.比如下面是N=4时的一种例子 3 1 2 4 4 3 6 7 9 16 在FJ回来之前,奶牛们开始了一个更难的游戏:他们尝试根据最后结果找到开始的序列.这已超过了FJ的思考极限. 写一个程序来帮助FJ吧 Input N和最后的和 Output 满足

POJ 题目Backward Digit Sums(next_permutation)

Backward Digit Sums Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 4807   Accepted: 2772 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 ad

bzoj1653:Backward Digit Sums

1653: [Usaco2006 Feb]Backward Digit Sums Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 318  Solved: 239[Submit][Status][Discuss] Description FJ and his cows enjoy playing a mental game. They write down the numbers from 1 to N (1 <= N <= 10) in a cer

BZOJ1653: [Usaco2006 Feb]Backward Digit Sums

1653: [Usaco2006 Feb]Backward Digit Sums Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 207  Solved: 161[Submit][Status][Discuss] Description FJ and his cows enjoy playing a mental game. They write down the numbers from 1 to N (1 <= N <= 10) in a cer

Backward Digit Sums(暴力)

Backward Digit Sums Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 5664   Accepted: 3280 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 ad

POJ3187 Backward Digit Sums 【暴搜】

Backward Digit Sums Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 4487   Accepted: 2575 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 ad

POJ 3187 Backward Digit Sums 题解 《挑战程序设计竞赛》

题目:POJ 3187 思路: 这道题很简单,用next_permutation枚举1~N的所有排列,然后依次相加,判断最后的和是否等于sum,是的话则break,即为字典序最前的. 1 #include <iostream> 2 #include <algorithm> 3 4 using namespace std; 5 6 int n; 7 int sum; 8 int mycase[11][11]; 9 10 int main() { 11 cin >> n &

Backward Digit Sums

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. Fo