1. 程式人生 > >第六屆藍橋杯【省賽試題9】壘骰子 ( 矩陣快速冪 )

第六屆藍橋杯【省賽試題9】壘骰子 ( 矩陣快速冪 )

題目描述:

賭聖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   
請嚴格按要求輸出,不要畫蛇添足地列印類似:“請您輸入...” 的多餘內容。  
所有程式碼放在同一個原始檔中,除錯通過後,拷貝提交該原始碼。  
注意: main函式需要返回0 
注意: 只使用ANSI C/ANSI C++ 標準,不要呼叫依賴於編譯環境或作業系統的特殊函式。 注意: 所有依賴的函式必須明確地在原始檔中 #include <xxx>, 不能通過工程設定而省略常用標頭檔案。  
提交時,注意選擇所期望的編譯器型別。

題目思路:

簡單矩陣快速冪的應用,求出遞推矩陣,程式設計實現即可。

遞推式:設dp[ i ][ j ]表示第 i 個骰子 j 面朝上的擺法有幾種


遞推矩陣:(根據遞推式很容易可以寫出)


矩陣T中 元素 T[ i ][ j ] 表示 i 面和 j 面的衝突關係

矩陣A中 元素A[ 1 ][ j ]表示 第1個骰子,j 面朝上的擺法有多少種,A乘一次T算出的是2個骰子。

最後,當一個面朝上的時候,骰子可以旋轉,讓別的面朝向不同,得到不同的擺法,所以最後要在得出的結果乘以 4^n

題目程式碼:

#include<cstdio>
#include<cstring>
#include<cmath>
#define MOD 1000000007
#define LL long long
using namespace std;

struct Matrix{
	LL v[6][6];
	Matrix(){memset(v,0,sizeof(v));}
};

Matrix mul(Matrix x ,Matrix y){
	Matrix ans;
	for(int i=0 ;i<6 ;i++){
		for(int j=0 ;j<6 ;j++){
			for(int k=0 ;k<6 ;k++){
				ans.v[i][j] = (ans.v[i][j] + x.v[i][k]*y.v[k][j])%MOD; 
			}
		}
	}
	return ans;
}

Matrix q_pow(Matrix x,int k){
	Matrix ans;
	for(int i=0 ;i<6 ;i++) ans.v[i][i] = 1;
	while(k){
		if(k&1) ans = mul(ans,x);
		x = mul(x,x);
		k >>= 1;
	}
	return ans;
}

int n,m,a,b;;

int main(){
	//初始化 
	Matrix T,ans;
	for(int i=0 ;i<6 ;i++){
		for(int j=0 ;j<6 ;j++){
			T.v[i][j] = 1;
		}
	}
	//資料輸入 
	scanf("%d%d",&n,&m);
	for(int i=0 ;i<m ;i++){
		scanf("%d%d",&a,&b);
		T.v[a-1][b-1] = 0; T.v[b-1][a-1] = 0;
	}	
	//資料處理 
	ans = q_pow(T,n-1);
	
	int sum = 0;
	for(int i=0 ;i<6 ;i++){
		for(int j=0 ;j<6 ;j++){
			sum = (sum+ans.v[i][j])%MOD;
		}
	}
	//結果輸出 
	printf("%d\n",(sum*((int)pow(4,n))%MOD)%MOD);
	
	return 0;
}


相關推薦

藍橋試題9 ( 矩陣快速 )

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

藍橋試題3三羊獻瑞

題目描述: 觀察下面的加法算式:   其中,相同的漢字代表相同的數字,不同的漢字代表不同的數字。  請你填寫“三羊獻瑞”所代表的4位數字(答案唯一),不要填寫任何多餘內容。 題目答案: 1085 

藍橋試題5取數位

題目描述: 求1個整數的第k位數字有很多種方法。 以下的方法就是一種。// 求x用10進製表示時的數位長度 int len(int x){ if(x<10) return 1; retur

藍橋試題2等差素數列

題目描述: 2,3,5,7,11,13,....是素數序列。 類似:7,37,67,97,127,157 這樣完全由素陣列成的等差數列,叫等差素數數列。 上邊的數列公差為30,長度為6。 2004年,

2017藍橋Java

第一題:購物單 小明剛剛找到工作,老闆人很好,只是老闆夫人很愛購物。老闆忙的時候經常讓小明幫忙到商場代為購物。小明很厭煩,但又不好推辭。 這不,XX大促銷又來了!老闆夫人開出了長長的購物單,都是有打折優惠的。  小明也有個怪癖,不到萬不得已,從不刷卡,直

2017藍橋Java有感

  相對於ACM程式設計大賽的難度,藍橋杯就算容易一些了,第八屆的難度比前兩屆也提高了不少,建議在HDOJ上多加練習,這樣就能輕鬆些。   從準備上講藍橋杯有很多題都有固定的套路,大量練習是必不可少的,校內選拔之後,就開始不斷的刷題總結的無限迴圈中。   臨

(藍橋個人賽)結果填空、程式碼填空

一、煤球數目(暴力解法,容易) 有一堆煤球,堆成三角稜錐形。具體: 第一層放1個, 第二層3個(排列成三角形), 第三層6個(排列成三角形), 第四層10個(排列成三角形), .... 如果一共有100層,共有多少個煤球? 請填表示煤球總數目的數字。 注

藍橋C++A組(A題平方和)

std image code 判斷 省賽 條件 alt com == 只需要按照題目暴力算就完事了,最後結果是2658417853,代碼如下: #include <bits/stdc++.h> typedef long long ll; bool

藍橋B組C++試題

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

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

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

加法變乘法——藍橋C語言B組(

clu 自己 nbsp 加法 藍橋杯 重新 () std spa 原創 加法變乘法 我們都知道:1+2+3+ ... + 49 = 1225現在要求你把其中兩個不相鄰的加號變成乘號,使得結果為2015 比如:1+2+3+...+10*11+12+...+27*28+29+

三羊獻瑞——藍橋C語言B組(三題

lan font oid 漢字 print ack size IV cnblogs 原創 三羊獻瑞 觀察下面的加法算式: 祥 瑞 生 輝 + 三 羊 獻 瑞 ------------------- 三 羊 生 瑞 氣 (如果有對齊問題,可以參看【圖1.jp

藍橋 軟體類真題 七題:加法變乘法

加法變乘法 我們都知道:1+2+3+ ... + 49 = 1225 現在要求你把其中兩個不相鄰的加號變成乘號,使得結果為2015 比如: 1+2+3+...+10*11+12+...+27*28+29+...+49 = 2015 就是符合要求的答案。 請你尋找另外一個可能

2015年藍橋C/C++程式設計本科B組-星系炸彈(結果填空)

#include <iostream> using namespace std; int isYear(int year) { if(year%4==0&&year%100!=0||year%400==0)) return 1; else

2015藍橋全國軟體大賽(預賽)總結

這是我上大學以來第一次自發的寫總結,這也許意味著我對大學的看法和接下來的大學生活都將有所改變吧。首先說說引導我寫這篇總結的“人物”吧,RUI,從大一開始便是同學,直到大三成為了舍友。他的成績一直很好,如果沒記錯的話,大一專業第一名,大二好像也是第一第二的,總之在班裡一直名列

2015年藍橋本科B組C++個人題解

比賽結束已經一星期了,成績也出來了,江蘇非211組的省前十,但是深感自己還是有太多的不足。絕對不能以自己還只是大一為藉口,acm這條路還長的很。 目測得了95分(滿分150),第一題錯了,程式碼填空第一題錯了,倒數第二題扣了一點分,最後一道大題全錯。 之所以會這麼

藍橋試題-- 解題報告

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

藍橋

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

-藍橋-生命之樹

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

藍橋測試1->2015年藍橋

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