欢迎访问我的新博客:http://www.milkcu.com/blog/
原文地址:http://www.milkcu.com/blog/archives/2014pa10.html
引言
这是2014年第五届蓝桥杯全国软件大赛预赛本科A组(C/C++组)第10题,也就是最后一题。
思路可以想得到,枚举和广度优先搜索,由于最后时间紧迫,简单的计数还没完成,谨以此文祭奠逝去的蓝桥杯。
题目描述
标题:波动数列
观察这个数列:
1 3 0 2 -1 1 -2 ...
这个数列中后一项总是比前一项增加2或者减少3。
栋栋对这种数列很好奇,他想知道长度为 n 和为 s 而且后一项总是比前一项增加a或者减少b的整数数列可能有多少种呢?
【数据格式】
输入的第一行包含四个整数 n s a b,含义如前面说述。
输出一行,包含一个整数,表示满足条件的方案数。由于这个数很大,请输出方案数除以100000007的余数。
例如,输入:
4 10 2 3
程序应该输出:
2
【样例说明】
这两个数列分别是2 4 1 3和7 4 1 -2。
【数据规模与约定】
对于10%的数据,1<=n<=5,0<=s<=5,1<=a,b<=5;
对于30%的数据,1<=n<=30,0<=s<=30,1<=a,b<=30;
对于50%的数据,1<=n<=50,0<=s<=50,1<=a,b<=50;
对于70%的数据,1<=n<=100,0<=s<=500,1<=a, b<=50;
对于100%的数据,1<=n<=1000,-1,000,000,000<=s<=1,000,000,000,1<=a, b<=1,000,000。
资源约定:
峰值内存消耗 < 256M
CPU消耗 < 1000ms
请严格按要求输出,不要画蛇添足地打印类似:“请您输入...” 的多余内容。
所有代码放在同一个源文件中,调试通过后,拷贝提交该源码。
注意: main函数需要返回0
注意: 只使用ANSI C/ANSI C++ 标准,不要调用依赖于编译环境或操作系统的特殊函数。
注意: 所有依赖的函数必须明确地在源文件中 #include <xxx>, 不能通过工程设置而省略常用头文件。
提交时,注意选择所期望的编译器类型。
分析
刚看这题,似乎摸不着头脑,细细欣赏,似乎还可以实现。
由于数据量可能很大,这里使用了long long类型。
输入给出了所有数的和s,假设该数列的第一个数为i,那么它的取值范围为[s - n * a, s + n * b]。
然后对枚举的每个数进行深度优先搜索,就可以得到结果。
考试时由于在main()函数内重复定义了变量cnt,和全局变量冲突,最后输出的答案一直是0,可惜没时间改了。
代码实现
#include <iostream> using namespace std; long long n, s, a, b; long long sum; long long cnt = 0; long long mo = 100000007; int dfs(long long nn, long long rn) { //cout << "dfs " << nn << ", " << rn << endl; sum += nn; if(rn == 0) { //cout << "sum " << sum << endl; if(sum == s) { sum -= nn; //cout << "cnt" << endl;; cnt++; cnt %= mo; return 1; } else { sum -= nn; return 0; } } dfs(nn + a, rn - 1); dfs(nn - b, rn - 1); sum -= nn; } int main(void) { cin >> n >> s >> a >> b; //dfs(2, 3); for(long long i = s - n * a; i < s + n * b; i++) { sum = 0; dfs(i, n - 1); } cout << cnt << endl; return 0; }
(全文完)