波動數列 - 藍橋杯

歡迎訪問我的新博客: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

發佈了98 篇原創文章 · 獲贊 12 · 訪問量 22萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章