波动数列 - 蓝桥杯

来源:互联网 发布:淘宝美工培训多少钱 编辑:程序博客网 时间:2024/04/30 09:23

欢迎访问我的新博客: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;}

(全文完)

本文地址:http://www.milkcu.com/blog/archives/2014pa10.html

0 0
原创粉丝点击