骰子 (入門概率DP)
阿新 • • 發佈:2019-01-24
【概率】骰子
時間限制: 1 Sec 記憶體限制: 128 MB
提交: 14 解決: 10
[提交] [狀態] [討論版] [命題人:admin]
題目描述
眾所周知,骰子是一個六面分別刻有一到六點的立方體,每次投擲骰子,從理論上講得到一點到六點的概率都是1/6。今有骰子一顆,連續投擲N次,問點數總和大於等於X的概率是多少?
輸入
一行兩個整數,分別表示n和x,其中1≤N≤24,0≤x<150。
輸出
一行,一個分數,要求以最簡的形式精確地表達出連續投擲N次骰子,總點數大於等於X的概率。如果是0/1就輸出0,如果是1/1,就輸出1。
樣例輸入
3 9
樣例輸出
20/27
友好的中文題面,通俗易懂的題意,初次接觸概率DP,略有不解,寫部落格以記之。
DP[i][j]表示拋i枚硬幣,點數和為j的方案數。因為每種方案都是等概率出現的,所以求得方案數之後除去總的方案數6^n就是最後的結果。方案數很容易計算,外層i從0到n-1表示拋第i枚硬幣,第二層j從0到i*6,列舉當前位置能達到的方案數,內層k從1到6,表示這次拋硬幣的結果對i+1次的影響。易得到狀態轉移:dp[i+1][j+k] += dp[i][j]
程式碼實現:
/* Look at the star Look at the shine for U */ #include<bits/stdc++.h> #define ll unsigned long long #define PII pair<int,int> #define sl(x) scanf("%lld",&x) using namespace std; const int N = 1e6+5; const int mod = 998244353; const int INF = 0x3f3f3f3f; ll inv(ll b){if(b==1)return 1; return (mod-mod/b)*inv(mod%b)%mod;} ll fpow(ll n,ll k){ll r=1;for(;k;k>>=1){if(k&1)r=r*n%mod;n=n*n%mod;}return r;} ll dp[1005][1005]; int main() { ll n,k,i,j,m; cin>>n>>m; dp[0][0] = 1; for(i = 0;i < n;i++) { for(j = 0;j <= i*6;j++) { for(k = 1;k <= 6;k++) dp[i+1][j+k] += dp[i][j]; } } ll ans = 0,temp = 1; for(i = m;i <= 6*n;i++) ans += dp[n][i]; for(i = 0;i < n;i++) temp *= 6; if(ans%temp == 0){cout<<ans/temp<<endl;return 0;} ll t = __gcd(ans,temp); cout<<ans/t<<"/"<<temp/t<<endl; }