1. 程式人生 > >第六屆藍橋杯省賽試題--壘骰子 解題報告

第六屆藍橋杯省賽試題--壘骰子 解題報告

PS: 關於本題演算法的優化演算法已經發表, 請檢視疊骰子( 以矩陣方法實現 )

原題:

賭聖atm晚年迷戀上了壘骰子,就是把骰子一個壘在另一個上邊,不能歪歪扭扭,要壘成方柱體。

經過長期觀察,atm 發現了穩定骰子的奧祕:有些數字的面貼著會互相排斥!
我們先來規範一下骰子:1 的對面是 4,2 的對面是 5,3 的對面是 6。
假設有 m 組互斥現象,每組中的那兩個數字的面緊貼在一起,骰子就不能穩定的壘起來。 
atm想計算一下有多少種不同的可能的壘骰子方式。
兩種壘骰子方式相同,當且僅當這兩種方式中對應高度的骰子的對應數字的朝向都相同。
由於方案數可能過多,請輸出模 10^9 + 7 的結果。
不要小看了 atm 的骰子數量哦~

「輸入格式」

第一行兩個整數 n m
n表示骰子數目
接下來 m 行,每行兩個整數 a b ,表示 a 和 b 數字不能緊貼在一起。


「輸出格式」
一行一個數,表示答案模 10^9 + 7 的結果。


「樣例輸入」
2 1
1 2


「樣例輸出」
544


「資料範圍」
對於 30% 的資料:n <= 5
對於 60% 的資料:n <= 100
對於 100% 的資料:0 < n <= 10^9, m <= 36


資源約定:
峰值記憶體消耗 < 256M

CPU消耗 < 2000ms

解題思路:

當我在考場上第一眼看到這道題的時候, 其實我是沒有思路的, 第一個在我腦海裡浮現出來的演算法是暴力破解, 但是看了看資料規模, 就立馬否決了, 後來就想到用動態規劃來解. Dp[ i ][ j ]表示高度為 i , 頂面點數為 j 的方案數, 那麼Dp[ i ][ j ] 就等於 i-1 高度時所有與j的反面無衝突的方案數累加. 最後的總方案數還要乘以(4^i), 因為每一個骰子可以4面轉嘛. 由於每一層的規劃只與前一層有關, 所以可以採用滾動陣列, 不然記憶體會超標...直接看程式碼吧!

#include <iostream>
using namespace std;

// ...衝突記錄: Compact[i][j]=false代表點數為i的面與點數為j的面存在衝突 
bool Compact[7][7];					

// ...Parner[i]=j代表 點數為i的面 的對立面點數為j	
const int Parner[7]={ 0,4,5,6,1,2,3 }; 
const long long MOD = 1000000007;

int main(int argc, char** argv) 
{
	long long  N; // 骰子高度
	int M; // 衝突組數
	int s1,s2; 
	cin >> N >> M;
	for( int i = 0; i < 7; ++i)
		for( int j = 0; j < 7;++j)
			Compact[i][j]=true;
			
	for( int i = 0; i < M; ++i ) {
		cin >> s1 >> s2;
		// ...點數為s1的面與點數為s2的面存在衝突 
		Compact[s1][s2] = Compact[s2][s1] = false;	
	}
	long long dp[2][7]; // 滾動陣列
	long long C = 4;
	int e = 0;			// 滾動標誌
	for( int i = 1; i < 7; ++i ) 
		dp[e][i] = 1;
	
	// dp[i][j]代表高度為i的,頂面點數為j的疊骰子方案數
	// 在這裡忽略每個骰子可以四面轉向的情況, 把該情況留到最後乘上去就可以了 
	int j,k;
	for( long long i = 2; i <= N; ++i ){
		e = 1-e;	// ...滾動處理 
		C = (C*4)%MOD;
		for( j = 1; j < 7; ++j ){
			dp[e][j] = 0;
			for( k = 1; k < 7; ++k)
				if( Compact[ Parner[j] ][k] )
					dp[e][j] += dp[1-e][k];
			dp[e][j]%=MOD;
		}
		
	}
	int sum=0;
	for( int i = 1; i < 7; ++i)
		sum = (sum+dp[e][i])%MOD;
	sum = (sum*C)%MOD;
	cout << sum;
	return 0;
}

總結 : 從上述程式碼可以看出, 這是一個時間複雜度為O(36n)的演算法, 為什麼我在強調O(36n)而不是O(n), 因為這個係數使得我沒有辦法通過資料規模為10^7以上的資料,  但是至今我仍未有任何辦法來減少這個係數, 希望大家能給提點建議.

PS: 關於本題演算法的優化演算法已經發表, 請檢視疊骰子( 以矩陣方法實現 )

相關推薦

藍橋試題-- 解題報告

PS: 關於本題演算法的優化演算法已經發表, 請檢視疊骰子( 以矩陣方法實現 ) 原題: 賭聖atm晚年迷戀上了壘骰子,就是把骰子一個壘在另一個上邊,不能歪歪扭扭,要壘成方柱體。 經過長期觀察,atm 發現了穩定骰子的奧祕:有些數字的面貼著會互相排斥! 我們先來規範一下骰子

藍橋試題-- 以矩陣的方法實現 解題報告

本貼宣告: 關於這道題的基本解法, 我在之前曾經發表過, 以動態規劃的方式在O(N)的時間複雜度內求解, 但對於資料規模為10^9的資料而已, O(N)顯然是不夠的, 當時我受困良久. 但幸運的是, 某網友給了我一個萬分有用的建議, 以矩陣的方式的進行求解. 當我實現以後,

藍橋試題1 煤球數目(遞推)

import java.util.Scanner; public class Test { public static void main(String[] args) { Scanner input=new Scanner(System.in); int n=100; long sum=0;

藍橋

一、三角形面積 如【圖1】所示。圖中的所有小方格面積都是1。 那麼,圖中的三角形面積應該是多少呢? 請填寫三角形的面積。不要填寫任何多餘內容或說明性文字。 分析:(該正方形的面積減去其他三

-藍橋-生命之樹

10、生命之樹 在X森林裡,上帝建立了生命之樹。他給每棵樹的每個節點(葉子也稱為一個節點)上,都標了一個整數,代表這個點的和諧值。上帝要在這棵樹內選出一個非空節點集S,使得對於S中的任意兩個點a,b,都存在一個點列 {a, v1, v2, ..., vk, b} 使得這個點

藍橋測試1->2015年藍橋

1.StringInGrid函式會在一個指定大小的格子中列印指定的字串。 要求字串在水平、垂直兩個方向上都居中。 如果字串太長,就截斷。 如果不能恰好居中,可以稍稍偏左或者偏上一點。 下面的程式實現這個邏輯,請填寫劃線部分缺少的程式碼。 #include <s

藍橋C/C++B組

程式設計的大題因為沒有辦法在OJ上提交,不知道是否能過100%的資料,但是大致就是這個意思。1.獎券數目有些人很迷信數字,比如帶“4”的數字,認為和“死”諧音,就覺得不吉利。雖然這些說法純屬無稽之談,但有時還要迎合大眾的需求。某抽獎活動的獎券號碼是5位數(10000-9999

藍橋Java語言C組_移動距離

移動距離 X星球居民小區的樓房全是一樣的,並且按矩陣樣式排列。其樓房的編號為1,2,3... 當排滿一行時,從下一行相鄰的樓往反方向排號。 比如:當小區排號寬度為6時,開始情形如下: 1  2  3

藍橋JAVA-B 全解析

手賤,提交錯了兩個順序,估計gg了 第一題: 我坑爹的竟然想到了用海倫公式,算出來24.92708569439206 唉,直接減去小的不就完事了啊````` 答案:8x8-(8x4)/2-4x6/2-8x2/2=28 第二題: 立方變自身 觀察下面的現象,某個數字的立方,

藍橋C/C++B組

壘骰子 賭聖atm晚年迷戀上了壘骰子,就是把骰子一個壘在另一個上邊,不能歪歪扭扭,要壘成方柱體。 經過長期觀察,atm 發現了穩定骰子的奧祕:有些數字的面貼著會互相排斥! 我們先來規範一下骰子:1 的對面是 4,2 的對面是 5,3 的對面是 6。 假設有 m 組互斥現象

2015年藍橋(C/C++ B組)解題報告

第1題:統計不含4的數字 題目大意   統計10000至99999中,不包含4的數值個數。 題解   (@『落』常笑鷹 提供)直接推匯出數學公式   最高位除了0、4不能使用,其餘8個數字(1,2,3,5,6,7,8,9)均能使用,剩下的四位(

【暴力自動生成排列】(2015)藍橋 C/C++ B組 題解(三題)

第三題題目三羊獻瑞觀察下面的加法算式:       祥 瑞 生 輝  +   三 羊 獻 瑞-------------------   三 羊 生 瑞 氣(如果有對齊問題,可以參看【圖1.jpg】)其中

2015年藍橋A組(C/C++)

部分轉載自:http://blog.csdn.net/summonlight/article/details/61920048還有:https://zhidao.baidu.com/question/310414478.html1. 方程整數解方程: a^2 + b^2 +

藍橋 三羊獻瑞

三羊獻瑞 觀察下面的加法算式:       祥 瑞 生 輝   +   三 羊 獻 瑞 -------------------    三 羊 生 瑞 氣 (如果有對齊問題,可以參看【圖1.jpg】) 其中,相同的漢字代表相同的數字,不同的漢字代表不同的數字。 請你填寫“三

藍橋2015本科B組c/++部分解題報告

今天是2015年4月11日,昨天剛從hz趕回來,好久不寫程式碼,手感有些生疏,~~ 一、獎券數目(3分) 有些人很迷信數字,比如帶“4”的數字,認為和“死”諧音,就覺得不吉利。 雖然這些說法純屬無稽之談,但有時還要迎合大眾的需求。某抽獎活動的獎券號碼是5位數(10000-9

2015藍橋決賽c/c++本科B組試題總結及解題答案

1. 積分之迷 小明開了個網上商店,賣風鈴。共有3個品牌:A,B,C。 為了促銷,每件商品都會返固定的積分。 小明開業第一天收到了三筆訂單:  第一筆:3個A + 7個B + 1個C,共返積分:315  第二筆:4個A + 10個B + 1個C,共返積分:420 

2016藍橋C組試題及部分答案

答案都是自己理解的 1.報紙頁數 X星球日報和我們地球的城市早報是一樣的,都是一些單獨的紙張疊在一起而已。每張紙印有4版。比如,某張報紙包含的4頁是:5,6,11,12,可以確定它應該是最上邊的第2張報紙。我們在太空中撿到了一張X星球的報紙,4個頁碼分別是: 1125,11

2016年藍橋A組試題

2016年第七屆藍橋杯省賽(C/C++) A組試題及參考答案 第七屆藍橋杯省賽結束了,趁著還有點印象,趕緊把答案記一下。 歡迎加入à程式設計學習交流QQ群:23228338,一起交流藍橋杯答案及程式設計交流學習。群檔案有答案下載 1.父親和兒子(列舉) 父親的年齡兩個數字

2016藍橋c/c++本科B組試題總結及解題答案

第一題:煤球數目第i層的煤球陣列為(1+n)*n/2,答案:171700第二題:生日蠟燭思路:1 2 3 4 5 6……這一個等差數列的前n項和為(1+n)*n/2設從a歲開始過生日,到了b歲一共吹熄了236根蠟燭。即為:(a+b)(b-a+1)/2=236,答案:26for

藍橋JavaB組題奇怪的分式

標題:奇怪的分式    上小學的時候,小明經常自己發明新演算法。一次,老師出的題目是:    1/4 乘以 8/5     小明居然把分子拼接在一起,分母拼接在一起,答案是:18/45 (參見圖1.pn