力扣題庫-擲骰子模擬詳細解析

題目如下:

有一個骰子模擬器會每次投擲的時候生成一個 1 到 6 的隨機數。

不過我們在使用它時有個約束,就是使得投擲骰子時,連續?擲出數字?i?的次數不能超過?rollMax[i]i?從 1 開始編號)。

現在,給你一個整數數組?rollMax?和一個整數?n,請你來計算擲?n?次骰子可得到的不同點數序列的數量。

假如兩個序列中至少存在一個元素不同,就認為這兩個序列是不同的。

由于答案可能很大,所以請返回?模?10^9 + 7?之后的結果。

限制如下

  • 1 <= n <= 5000
  • rollMax.length == 6
  • 1 <= rollMax[i] <= 15

解析如下:

在不考慮rollMax?限制情況下

若第1次投擲1~6,連續1次點數相同,則每個點數各有1種,即d[1][i][1] = 1(初始值),定義i為

????????????????第一次可能投擲出的點數,X為第一次已經投擲出的點數,則第一次投擲結果表示為? X?

若第2次投擲1~6,連續2次點數相同,則每個點數各有1種,即d[2][i][2] = 1,i為第二次可能投擲

????????????????出的點數,Y為第二次已經投擲出的點數,則兩次投擲出的結果表示為 XY,且X=Y,

????????????????則d[2][i][2] = d[1][i][1]

????????????????投擲1~6,連續1次點數相同, 則兩次投擲出的結果表示為 XY,且X != Y,在Y確定時,

? ? ? ? ? ? ? ? 只需考慮前一次的情況,即X的值,X有6-1種選擇,即d[2][i][1] = d[1][j][1] * 5 ,此處

????????????????*5表示第一次投擲d[1][i][1] 6種情況 減去X=Y這種情況的累加,

????????????????d[2][i][1] =?d[1][a][1]+d[1][b][1]+d[1][c][1]+d[1][d][1]+d[1][e][1]

若第3次投擲1~6,連續3次點數相同, 則每個點數各有1種,即d[3][i][3] = 1,i為第三次可能投擲

????????????????出的點數,Z為第三次已經投擲出的點數,則三次投擲出的結果表示為 XYZ,X=Y=Z,

? ? ? ? ? ? ? ? 在Z確定時,只需要考慮前兩次的投擲情況,即XY的值,因為X=Y,所以只考慮第二次

????????????????投擲1~6,連續2次點數相同的情況即d[2][i][2]的情況,又因為Z?= Y,所以Y只有一種選

????????????????擇,所以d[3][i][3] =?d[2][i][2] = d[1][i][1]

????????????????投擲1~6,連續2次點數相同, 則三次投擲出的結果表示為 XYZ,且Z?= Y != X,在Z

????????????????確定時,只需要考慮前兩次的投擲情況,即XY的值,因為Y != X,所以只考慮第二次

????????????????投擲1~6,連續1次點數相同的情況即d[2][i][1]的情況,

????????????????又因為Z?= Y,所以Y只有一種選擇,所以d[3][i][2] =?d[2][i][1]

????????????????投擲1~6,連續1次點數相同,則三次投擲出的結果表示為 XYZ,且Z != Y,Y與X可相等

????????????????可不等,

????????????????先考慮Y != X情況,在Z確定時,只需要考慮前兩次的投擲情況,即XY的值,因為Y != ????????????????X,所以只考慮第二次投擲1~6,連續1次點數相同的情況即d[2][i][1]的情況,

????????????????又因為Z != Y,所以Y有6-1種選擇,

????????????????即d[3][i][1] =? d[2][i][1] * 5 = d[2][a][1]+d[2][b][1]+d[2][c][1]+d[2][d][1]+d[2][e][1]

? ? ? ? ? ? ? ? 再考慮Y=X情況,在Z確定時,只需要考慮前兩次的投擲情況,即XY的值,

????????????????因為Y = X,所以只考慮第二次投擲1~6,連續2次點數相同的情況即d[2][i][2]的情況,

????????????????又因為Z != Y,所以Y有6-1種選擇,

? ? ? ? ? ? ? ? 即d[3][i][1] =?d[2][i][2] * 5 =?d[2][a][2]+d[2][b][2]+d[2][c][2]+d[2][d][2]+d[2][e][2]注意從

? ? ? ? ? ? ? ? 此處開始就需要考慮rollMax?的影響,暫時先忽略

? ? ? ? ? ? ? ? 將上述兩種情況相加可得:d[3][i][1] =?d[2][a][1]+d[2][b][1]+d[2][c][1]+d[2][d][1]+d[2][e][1] +?d[2][a][2]+d[2][b][2]+d[2][c][2]+d[2][d][2]+d[2][e][2],可以轉變為下面的代碼

d[3][i][1] = 0;
for(int v = 1; v <= 6; v++)
{for(int k = 1; k <= 2; k++){if(v != i){d[3][i][1] += d[2][v][k];}}
}

由上述幾種投擲情況,可以發現,連續1次點數相同情況特殊,需要找上一次投擲的所用情況中排除,而超過1次點數相同情況只需要找上一次投擲中對應次數-1的結果即可,總結如下

第n次投擲1~6,連續1次點數相同的即d[n][i][1]的值為第n-1次投擲連續1次,2次到n-1次點數相同的所有情況減去每種情況下點數與i相同的情況的總和,如下

for(int v = 1; v <= 6; v++)
{for(int k = 1; k <= n - 1; k++){if(v != i){d[n][i][1] += d[n-1][v][k];}}
}
帶入n = 2,結果正確

第n次投擲1~6,連續k次點數相同(k>1)的即d[n][i][k]的值第n-1次投擲連續k-1次點數相同的6種情況中第n-1次投擲與第n次投擲結果相同的一種情況,即d[n][i][k] = d[n - 1][i][k-1]

由上述總結可以得到如下的忽略rollMax?的代碼

const int MOD = 1000000007;int DieSimulator2(int n)
{//狀態 d[i][j][k] 表示已經完成了 i 次擲骰子,第 i 次擲的是 j,并且已經連續擲了 k 次 j 的方案數。//投擲從1開始算,所以為 n+1int[][][] d = new int[n + 1][][];for (int i = 0; i <= n; i++){d[i] = new int[6][];for (int j = 0; j < 6; j++){//此處的16表示最多連續15次,由1 <= rollMax[i] <= 15得到d[i][j] = new int[16];}}//第一次投擲出且連續擲出j的方案數只能是1,用0~5來代替投擲出1~6的點數for (int j = 0; j < 6; j++){d[1][j][1] = 1;}//第一次投擲結果已知,從第二次開始for(int i = 2; i <= n; i++){//本次投擲的結果for(int j = 0; j < 6; j++){//本次投擲的連續次數for(int k = 1; k <= n; k++){if(k != 1){//本次投擲連續次數不為1,結果為i-1次投擲中,結果為j且連續k-1次的情況d[i][j][k] += d[i - 1][j][k - 1];d[i][j][k] %= MOD;}else{//本次投擲連續次數為1,結果為i-1次投擲中,結果不為j,連續次數隨意的情況總和//p為i-1次投擲的結果for (int p = 0; p < 6; p++){//lk為i-1次投擲結果的連續次數,lk不能超過ifor (int lk = 1; lk < i; lk++){//j與p不等情況的累加if(j != p){d[i][j][1] += d[i - 1][p][lk]; d[i][j][1] %= MOD;}}}}}}}int res = 0;for (int j = 0; j < 6; j++){for (int k = 1; k <= n; k++){res = (res + d[n][j][k]) % MOD;}}return res;
}

現在開始考慮rollMax的限制條件,替換其實很簡單,就是在對投擲點數的連續次數的循環上加上限制即可,比如在計算本次連續投擲次數時 for(int k = 1; k <= n; k++) //本次投擲的連續次數原先的限制為連續次數不能超過總投擲次數,改為 for(int k = 1; k <= rollMax[j]; k++),不能超過rollMax對應值限制的次數即可,以及在計算本次投擲連續次數為1時,使用上一次投擲情況的地方?for (int lk = 1; lk < i; lk++) //lk為i-1次投擲結果的連續次數,原限制為連續次數不能超出i-1的投擲次數,改為for (int lk = 1; lk <= rollMax[p]; lk++),變為不能超過rollMax上次投擲值對應限制的次數即可,最后在計算總數時,一樣加上限制即可。

添加限制后的代碼如下

const int MOD = 1000000007;public int DieSimulator(int n, int[] rollMax)
{//狀態 d[i][j][k] 表示已經完成了 i 次擲骰子,第 i 次擲的是 j,并且已經連續擲了 k 次 j 的方案數。//投擲從1開始算,所以為 n+1int[][][] d = new int[n + 1][][];for (int i = 0; i <= n; i++){d[i] = new int[6][];for (int j = 0; j < 6; j++){//此處的16表示最多連續15次,由1 <= rollMax[i] <= 15得到d[i][j] = new int[16];}}//第一次投擲出且連續擲出j的方案數只能是1,用0~5來代替投擲出1~6的點數for (int j = 0; j < 6; j++){d[1][j][1] = 1;}//第一次投擲結果已知,從第二次開始for(int i = 2; i <= n; i++){//本次投擲的結果for(int j = 0; j < 6; j++){//本次投擲的連續次數for(int k = 1; k <= rollMax[j]; k++){if(k != 1){//本次投擲連續次數不為1,結果為i-1次投擲中,結果為j且連續k-1次的情況d[i][j][k] += d[i - 1][j][k - 1];d[i][j][k] %= MOD;}else{//本次投擲連續次數為1,結果為i-1次投擲中,結果不為j,連續次數隨意的情況總和//p為i-1次投擲的結果for (int p = 0; p < 6; p++){//lk為i-1次投擲結果的連續次數for (int lk = 1; lk <= rollMax[p]; lk++){//j與p不等情況的累加,且上次投擲連續次數不能超過當前投擲次數if(j != p && lk < i){d[i][j][1] += d[i - 1][p][lk];d[i][j][1] %= MOD;}}}}}}}int res = 0;for (int j = 0; j < 6; j++){for (int k = 1; k <= rollMax[j]; k++){res = (res + d[n][j][k]) % MOD;}}return res;
}

到這,解析就結束了,當然還有優化空間,但這已經石是我自己研究出來的結果了

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/62235.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/62235.shtml
英文地址,請注明出處:http://en.pswp.cn/web/62235.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

深入淺出:PHP中的數據類型全解析

文章目錄 引言理解數據類型標量類型整數 (integer)浮點數 (float)布爾值 (boolean)字符串 (string) 復合類型數組 (array)對象 (object)資源 (resource)NULL 特殊類型Callable強制類型轉換 實戰案例總結與展望參考資料 引言 在編程的世界里&#xff0c;數據類型是構建任何應用…

當linux可執行文件缺少或者不兼容so庫時候,如何查看版本以及缺少那些庫

解決方法&#xff1a; ldd 命令來驗證程序是否加載了正確的庫&#xff1a; 如檢查linear_elasticity可執行文件缺少的庫&#xff0c;用下面命令&#xff1a; ldd linear_elasticity 可以發現下面not found就是缺少的庫&#xff0c;還有對應的庫的位置已經版本 $ ldd lin…

第P1周:Pytorch實現mnist手寫數字識別

&#x1f368; 本文為&#x1f517;365天深度學習訓練營 中的學習記錄博客&#x1f356; 原作者&#xff1a;K同學啊 目標 1. 實現pytorch環境配置 2. 實現mnist手寫數字識別 3. 自己寫幾個數字識別試試具體實現 &#xff08;一&#xff09;環境 語言環境&#xff1a;Python…

Seq2Seq模型的發展歷史;深層RNN結構為什么出現梯度消失/爆炸問題,Transformer為什么不會;Seq2Seq模型存在問題

目錄 Seq2Seq模型的發展歷史 改進不足的地方 深層RNN結構為什么出現梯度消失/爆炸問題,Transformer為什么不會 深層RNN結構為什么出現梯度消失/爆炸問題: Transformer為什么不會出現梯度消失/爆炸問題: Seq2Seq模型存在問題 T5模型介紹 Seq2Seq模型的發展歷史 序列到…

網絡安全技術詳解:虛擬專用網絡(VPN) 安全信息與事件管理(SIEM)

虛擬專用網絡&#xff08;VPN&#xff09;詳細介紹 虛擬專用網絡&#xff08;VPN&#xff09;通過在公共網絡上創建加密連接來保護數據傳輸的安全性和隱私性。 工作原理 VPN的工作原理涉及建立安全隧道和數據加密&#xff1a; 隧道協議&#xff1a;使用協議如PPTP、L2TP/IP…

Hive 窗口函數與分析函數深度解析:開啟大數據分析的新維度

Hive 窗口函數與分析函數深度解析&#xff1a;開啟大數據分析的新維度 在當今大數據蓬勃發展的時代&#xff0c;Hive 作為一款強大的數據倉庫工具&#xff0c;其窗口函數和分析函數猶如一把把精巧的手術刀&#xff0c;助力數據分析師們精準地剖析海量數據&#xff0c;挖掘出深…

SCAU期末筆記 - 數據庫系統概念

我校使用Database System Concepts&#xff0c;9-12章不考所以跳過&#xff0c;因為課都逃了所以復習很倉促&#xff0c;只準備過一下每一章最后的概念辨析&#xff0c;我也不知道有沒有用 第1章 引言 數據庫管理系統&#xff08;DBMS&#xff09; 由一個互相關聯的數據的集合…

Android 12系統源碼_窗口管理(九)深淺主題切換流程源碼分析

前言 上一篇我們簡單介紹了應用的窗口屬性WindowConfiguration這個類&#xff0c;該類存儲了當前窗口的顯示區域、屏幕的旋轉方向、窗口模式等參數&#xff0c;當設備屏幕發生旋轉的時候就是通過該類將具體的旋轉數據傳遞給應用的、而應用在加載資源文件的時候也會結合該類的A…

河南省的教育部科技查新工作站有哪些?

鄭州大學圖書館&#xff08;Z12&#xff09;&#xff1a;2007年1月被批準設立“教育部綜合類科技查新工作站”&#xff0c;同年12月被河南省科技廳認定為河南省省級科技查新機構。主要面向河南省的高校、科研機構、企業提供科技查新、查收查引等服務。 河南大學圖書館&#xf…

Leetcode經典題6--買賣股票的最佳時機

買賣股票的最佳時機 題目描述&#xff1a; 給定一個數組 prices &#xff0c;它的第 i 個元素 prices[i] 表示一支給定股票第 i 天的價格。 你只能選擇 某一天 買入這只股票&#xff0c;并選擇在 未來的某一個不同的日子 賣出該股票。設計一個算法來計算你所能獲取的最大利潤。…

MCPTT 與BTC

MCPTT&#xff08;Mission Critical Push-to-Talk&#xff09;和B-TrunC&#xff08;寬帶集群&#xff09;是兩種關鍵通信標準&#xff0c;它們分別由不同的組織制定和推廣。 MCPTT&#xff08;Mission Critical Push-to-Talk&#xff09;標準由3GPP&#xff08;第三代合作伙伴…

去除賬號密碼自動賦值時的輸入框背景色

問題描述&#xff1a; 前端使用賬號密碼登錄&#xff0c;若在網頁保存過當前頁面的密碼和賬號&#xff0c;那么當再次進入該頁面&#xff0c;網頁會自動的把賬號和密碼賦到輸入框中&#xff0c;而此時輸入框是帶有背景色的&#xff0c;與周邊的白色背景顯得很不協調&#xff1…

【Pytorch】torch.reshape與torch.Tensor.reshape區別

問題引入&#xff1a; 在Pytorch文檔中&#xff0c;有torch.reshape與torch.Tensor.reshape兩個reshape操作&#xff0c;他們的區別是什么呢&#xff1f; 我們先來看一下官方文檔的定義&#xff1a; torch.reshape&#xff1a; torch.Tensor.reshape: 解釋&#xff1a; 在p…

掃碼與短信驗證碼登錄JS逆向分析與Python純算法還原

文章目錄 1. 寫在前面2. 掃碼接口分析2. 短信接口分析3. 加密算法還原【??作者主頁】:吳秋霖 【??作者介紹】:擅長爬蟲與JS加密逆向分析!Python領域優質創作者、CSDN博客專家、阿里云博客專家、華為云享專家。一路走來長期堅守并致力于Python與爬蟲領域研究與開發工作!…

spring6:3容器:IoC

spring6&#xff1a;3容器&#xff1a;IoC 目錄 spring6&#xff1a;3容器&#xff1a;IoC3、容器&#xff1a;IoC3.1、IoC容器3.1.1、控制反轉&#xff08;IoC&#xff09;3.1.2、依賴注入3.1.3、IoC容器在Spring的實現 3.2、基于XML管理Bean3.2.1、搭建子模塊spring6-ioc-xml…

【認證法規】安全隔離變壓器

文章目錄 定義反激電源變壓器 定義 安全隔離變壓器&#xff08;safety isolating transformer&#xff09;&#xff0c;通過至少相當于雙重絕緣或加強絕緣的絕緣使輸入繞組與輸出繞組在電氣上分開的變壓器。這種變壓器是為以安全特低電壓向配電電路、電器或其它設備供電而設計…

車機端同步outlook日歷

最近在開發一個車機上的日歷助手&#xff0c;其中一個需求就是要實現手機端日歷和車機端日歷數據的同步。然而這種需求似乎沒辦法實現&#xff0c;畢竟手機日歷是手機廠商自己帶的系統應用&#xff0c;根本不能和車機端實現數據同步的。 那么只能去其他公共的平臺尋求一些機會&…

OpenCV-圖像閾值

簡單閾值法 此方法是直截了當的。如果像素值大于閾值&#xff0c;則會被賦為一個值&#xff08;可能為白色&#xff09;&#xff0c;否則會賦為另一個值&#xff08;可能為黑色&#xff09;。使用的函數是 cv.threshold。第一個參數是源圖像&#xff0c;它應該是灰度圖像。第二…

力扣300.最長遞增子序列

題目描述 題目鏈接300. 最長遞增子序列 給你一個整數數組 nums &#xff0c;找到其中最長嚴格遞增子序列的長度。 子序列 是由數組派生而來的序列&#xff0c;刪除&#xff08;或不刪除&#xff09;數組中的元素而不改變其余元素的順序。例如&#xff0c;[3,6,2,7] 是數組 […

Vue CLI的作用

Vue CLI&#xff08;Command Line Interface&#xff09;是一個基于Vue.js的官方腳手架工具&#xff0c;其主要作用是幫助開發者快速搭建Vue項目的基礎結構和開發環境。以下是Vue CLI的具體作用&#xff1a; 1、項目模板與快速生成 Vue CLI提供了一系列預設的項目模板&#x…