1. 程式人生 > >【藍橋杯】- 壘骰子(確保正確的解答)

【藍橋杯】- 壘骰子(確保正確的解答)

超時 include true res pan oppo == com 技術分享

百度出來的找了四篇看了下,都是錯的,除了技術分享圖片之外,數據輸出全都不一樣。

這題乍一看是個DFS,但是數據太大了,DFS穩穩的超時,要用快速冪,我用DFS純暴力的方法試了答案,所以我敢說確保正確。

這是用DFS寫的:

#include <iostream>
using namespace std;
#define mod 1000000007

int opposite[7] = { 0,4,5,6,1,2,3 };
int side[7][5] = {
    { 0,0,0,0,0 },
    { 0,2,3,5,6 },
    { 0,1,3,4,6 },
    { 0,1,2,4,5 },
    { 0,2
,3,5,6 }, { 0,1,3,4,6 }, { 0,1,2,4,5 }, }; bool flag[7][7]; int res = 0; int n, m; void DFS(int height, int front, int up) { if (height == n) { res = res % mod + 1; return; } for (int i = 1; i <= 6; i++) { for (int j = 1; j <= 4; j++) { if (height == 0
|| !flag[up][opposite[side[i][j]]]) { DFS(height + 1, i, side[i][j]); } } } } int main() { cin >> n >> m; for (int i = 0; i < m; i++) { int t1, t2; cin >> t1 >> t2; flag[t1][t2] = flag[t2][t1] = true; } DFS(
0, 0, 0); cout << res << endl; return 0; }

我們一點一點來分析,首先要知道篩子有6個面,每個面有4個側面,所以每個篩子有24種體位(我實在不知道用什麽來形容合適)。

技術分享圖片

假設骰子從下往上依次是A,B,C……(後面都一樣,不再寫了),來看這三個測試數據:

2個骰子,0種排斥,就是24*24=576;

2個骰子,1種排斥,A骰子1朝上有四種,B骰子1朝下也是四種,4*4=16,這16種是不能出現的,576-16=560。(參見說的都是這裏)

2個骰子,1種排斥,A骰子1朝上有四種,B骰子2朝下也是有四種;A骰子2朝上有四種,B骰子1朝下也是有四種,4*4+4*4=32,576-32=544。

要分清楚,1 1和1 2的區別,1不能貼著2,2也不能貼著1啊(這就跟:擲兩個骰子,擲到兩個1的概率是1/36,擲到一個1,一個2的概率是1/18);


然後我們繼續看三個骰子的:

技術分享圖片

3個骰子,0種排斥,24^3=13824;

3個骰子,1種排斥,A和B互斥面緊貼有16種情況(參見 2個骰子,1種排斥情況),C骰子就不受限制了,16*24=384,同理BC緊貼,A不受限制也是384種;13824-768=13056

第三個測試數據和2個骰子時是一個道理,就不寫了。


再看四個骰子的:

技術分享圖片

直接看第二個測試數據,講不清楚了,畫了個圖:

技術分享圖片

可以算一下,這些加起來,就是上面兩個測試數據的差。


10^9的解答,我還沒做出來,但到這,已經可以證明至少 我這答案是對的。

【藍橋杯】- 壘骰子(確保正確的解答)