反过来推

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

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

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

  

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

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

  

 #include <iostream>
#include <functional>
#include <algorithm> using namespace std; static int set[], tmp[];
static int sum, length; void enum_string(const int,const int);
bool scmop(void); int main(void)
{
while (~scanf("%d%d", &length, &sum))
{
for (int i = ; i <= length; i++)
tmp[i - ] = i;
if (length == && tmp[] == sum)
{
for (int i = ; i < length; i++)
printf("%d ", tmp[i]);
printf("\n");
continue;
}
do{
for (int i = ; i < length - ; i++)
set[i] = tmp[i] + tmp[i + ];
for (int i = length - ; i >= ; i--)
{
for (int j = ; j < i; j++)
set[j] = set[j] + set[j + ];
}
if (set[] == sum)
{
for (int i = ; i < length; i++)
printf("%d ", tmp[i]);
printf("\n");
break;
}
} while (next_permutation(tmp, tmp + length)); }
return ;
}

    

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

    

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

  

 #include <iostream>
#include <functional>
#include <algorithm> using namespace std; static int set_sum, tmp[], Cn[];
static int sum, length; void Cal_Cn(const int); int main(void)
{
while (~scanf("%d%d", &length, &sum))
{
for (int i = ; i <= length; i++)
tmp[i - ] = i;
memset(Cn, , sizeof(Cn));
Cal_Cn(length);
if (length == && tmp[] == sum)
{
for (int i = ; i < length; i++)
printf("%d ", tmp[i]);
printf("\n");
continue;
}
do{
set_sum = ;
for (int i = ; i < length; i++)
set_sum += Cn[i] * tmp[i];
if (set_sum == sum)
{
for (int i = ; i < length; i++)
printf("%d ", tmp[i]);
printf("\n");
break;
}
} while (next_permutation(tmp, tmp + length));
}
return ;
} void Cal_Cn(const int length)
{
Cn[] = ;
for (int j = ; j < length; j++)
{
Cn[j] = length - ;
for (int k = ; k <= j; k++)
Cn[j] *= (length - k);
for (int k = ; k <= j; k++)
Cn[j] /= k;
}
}

  

  最后,32ms

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

  1. POJ 3187 Backward Digit Sums 枚举水~

    POJ 3187  Backward Digit Sums http://poj.org/problem?id=3187 题目大意: 给你一个原始的数字序列: 3   1   2   4  他可以相邻 ...

  2. Backward Digit Sums(POJ 3187)

    Backward Digit Sums Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 5495   Accepted: 31 ...

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

    -->Backward Digit Sums 直接写中文了 Descriptions: FJ 和 他的奶牛们在玩一个心理游戏.他们以某种方式写下1至N的数字(1<=N<=10). 然 ...

  4. BZOJ1653: [Usaco2006 Feb]Backward Digit Sums

    1653: [Usaco2006 Feb]Backward Digit Sums Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 207  Solved:  ...

  5. Backward Digit Sums(暴力)

    Backward Digit Sums Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 5664   Accepted: 32 ...

  6. 1653: [Usaco2006 Feb]Backward Digit Sums

    1653: [Usaco2006 Feb]Backward Digit Sums Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 285  Solved:  ...

  7. POJ3187 Backward Digit Sums 【暴搜】

    Backward Digit Sums Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 4487   Accepted: 25 ...

  8. P1118 [USACO06FEB]Backward Digit Sums G/S

    P1118 [USACO06FEB]Backward Digit Sums G/S 题解:  (1)暴力法.对1-N这N个数做从小到大的全排列,对每个全排列进行三角形的计算,判断是否等于N.  对每个 ...

  9. 穷竭搜索:POJ 3187 Backward Digit Sums

    题目:http://poj.org/problem?id=3187 题意: 像这样,输入N : 表示层数,输入over表示最后一层的数字,然后这是一个杨辉三角,根据这个公式,由最后一层的数,推出第一行 ...

随机推荐

  1. 【CodeForces 596A】E - 特别水的题5-Wilbur and Swimming Pool

    Description After making bad dives into swimming pools, Wilbur wants to build a swimming pool in the ...

  2. 【Gym 100733D】Little thief Shi

    题 Shi realized that he was almost out of money, even renting Shitalian lands. Shi was walking on a s ...

  3. 云,git,blog,感想

    最近由于工作的原因,又看了一下git的资料,这次看收获不小,因为之前已经用了一段时间的git了.主要收获就是除了工作,自己平时在练习时使用git也会事半功倍,怎么说呢,没有git之前,相信很多自学的人 ...

  4. Java Observer 观察者

    http://www.cnblogs.com/jaward/p/3277619.html 1.API 被观察者 java.util.Observable; public class Observabl ...

  5. 提示用户一直输入数字(默认为正整数),当用户输入end的时候显示当前输入数字中的最大值。

    string input = ""; ; while (input != "end") { Console.WriteLine("请输入一个正整数,输 ...

  6. 初学JDBC,获取插入记录的主键、执行批量操作

    一.获取插入记录主键值 在创建语句的地方使用Statement.RETURN_GENERATED_KEYS标识一下,然后通过getGeneratedKeys方法获得 preparedStatement ...

  7. Linux之入侵痕迹清理总结

    rm -f -r /var/log/*rm .bash_historyrm recently_used

  8. myBatis 实现用户表增删查改操作<方法1 没有使用接口的>(最终版)

    在UserMapper.xml中添加增删改查 <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYP ...

  9. windows下使用批处理文件调用python程序

    这个随笔涉及到几个批处理脚本得知识点. windows的start命令, 启动另一个窗口运行指定的程序或命令. windows的call命令, 从批处理程序调用另一个程序, 直到被调用程序退出, 再继 ...

  10. POJ 1836 Alignment

    Alignment Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 11450 Accepted: 3647 Descriptio ...