Enum:Backward Digit Sums(POJ 3187)

题目大意:就是农夫和这只牛又杠上了(怎么老是牛啊,能换点花样吗),给出一行数(从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)的更多相关文章
- POJ 3187 Backward Digit Sums 枚举水~
POJ 3187 Backward Digit Sums http://poj.org/problem?id=3187 题目大意: 给你一个原始的数字序列: 3 1 2 4 他可以相邻 ...
- Backward Digit Sums(POJ 3187)
Backward Digit Sums Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 5495 Accepted: 31 ...
- 【POJ - 3187】Backward Digit Sums(搜索)
-->Backward Digit Sums 直接写中文了 Descriptions: FJ 和 他的奶牛们在玩一个心理游戏.他们以某种方式写下1至N的数字(1<=N<=10). 然 ...
- BZOJ1653: [Usaco2006 Feb]Backward Digit Sums
1653: [Usaco2006 Feb]Backward Digit Sums Time Limit: 5 Sec Memory Limit: 64 MBSubmit: 207 Solved: ...
- Backward Digit Sums(暴力)
Backward Digit Sums Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 5664 Accepted: 32 ...
- 1653: [Usaco2006 Feb]Backward Digit Sums
1653: [Usaco2006 Feb]Backward Digit Sums Time Limit: 5 Sec Memory Limit: 64 MBSubmit: 285 Solved: ...
- POJ3187 Backward Digit Sums 【暴搜】
Backward Digit Sums Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 4487 Accepted: 25 ...
- P1118 [USACO06FEB]Backward Digit Sums G/S
P1118 [USACO06FEB]Backward Digit Sums G/S 题解: (1)暴力法.对1-N这N个数做从小到大的全排列,对每个全排列进行三角形的计算,判断是否等于N. 对每个 ...
- 穷竭搜索:POJ 3187 Backward Digit Sums
题目:http://poj.org/problem?id=3187 题意: 像这样,输入N : 表示层数,输入over表示最后一层的数字,然后这是一个杨辉三角,根据这个公式,由最后一层的数,推出第一行 ...
随机推荐
- opencv笔记6:角点检测
time:2015年10月09日 星期五 23时11分58秒 # opencv笔记6:角点检测 update:从角点检测,学习图像的特征,这是后续图像跟踪.图像匹配的基础. 角点检测是什么鬼?前面一篇 ...
- codeforces 720A:Closing ceremony
Description The closing ceremony of Squanch Code Cup is held in the big hall with n × m seats, arran ...
- TCP/IP详解 笔记八
UDP协议 UDP是传输层协议,提供无连接不可靠的数据传输,其优点失效率高,确定确定是无序不可靠. 报文格式 UDP头部 TCP和UDP的端口号是独立的 UDP长度是指UDP数据报的总长度 UDP的校 ...
- linux java cpu 100%
1.用top找到最耗资源的进程id [ bin]# toptop - 16:56:14 up 119 days, 6:17, 7 users, load average: 2.04, 2.07, 2. ...
- HD2157How many wasy??(十大矩阵问题之八 + 邻接矩阵的应用)
How many ways?? Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)T ...
- HD1532Drainage Ditches(最大流模板裸题 + 邻接表)
Drainage Ditches Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) ...
- Spynner 安装
Spynner 安装 Windows7 下安装 1.easy_install spynner 2.下载pyqt sip https://sourceforge.net/projects/pyqt/fi ...
- 验证码点击刷新 this.src=this.src+'?'+Math.random()
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- APN APN指一种网络接入技术,是通过手机上网时必须配置的一个参数,它决定了手机通过哪种接入方式来访问网络。
apn 锁定 本词条由“科普中国”百科科学词条编写与应用工作项目 审核 . APN指一种网络接入技术,是通过手机上网时必须配置的一个参数,它决定了手机通过哪种接入方式来访问网络. 对于手机用户来说,可 ...
- JVM是如何分配和回收内存?有实例!
上一篇博客我简单介绍了下如何手动计算一个Java对象到底占用多少内存?今天就想聊下这个内存JVM到底是是如何分配和回收的. Java整体来说还是一个GC比较友好的语言,无论是分代的垃圾收集,还是基于G ...