NC23413小A买彩票

小A买彩票(概率/线性DP)

链接:https://ac.nowcoder.com/acm/problem/23413

小A最近开始沉迷买彩票,并且希望能够通过买彩票发家致富。已知购买一张彩票需要3元,而彩票中奖的金额分别为1,2,3,4元,并且比较独特的是这个彩票中奖的各种金额都是等可能的。现在小A连续购买了n张彩票,他希望你能够告诉他至少能够不亏本的概率是多少。
定义dp[i][j]表示i张彩票,j元的方案数
那么可以得到,i张彩票时回本的方案数是
ans = dp[i][3i]+....+dp[i][4i]
如何求,dp[i][j]?
dp[i][j] = dp[i-1][j-k](k = 1,2,3,4)
只考虑这一张的情况。

最后用gcd处理就行了。
code:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <queue>
#include <vector>
#include <deque>
#include <bitset>
using namespace std;
#define lowbit(x) x&-x
#define ll long long
#define dob double
#define For(i,s,n) for(int i = s;i <= n;i++)
#define mem0(a) memset(a,0,sizeof a)
#define gcd(a,b) __gcd(a,b)
const int N = 125;
const double eps = 1e-6;
const ll mod = 2333;
const int inf = 0x3f3f3f3f;
void read(int &res){
    char c;bool flag = true;
    while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1;res=c-'0';
    while((c=getchar())>='0'&&c<='9')res=res*10+c-'0';res*=flag;
}
ll s[N*100],dp[N][N] = {0};
//bool vis[N][N] = {false};
ll n;
void dfs(ll x,ll y){
    //cout<<x<<' '<<y<<endl;
    if(y < x || y > x*4) return;
    if(x < 1||y < 1) return;
    if(dp[x][y]) return;
    For(i,1,4){
        dfs(x-1,y-i);
        dp[x][y] += dp[x-1][y-i];
    }
}
int main(){
    ios::sync_with_stdio(false);
    cout.tie(NULL);
    //cout<<pow(4,30)<<endl;
    while(cin>>n) {
        if(n == 0){
            cout<<"1/1"<<endl;
        }else{
            dp[1][1] = dp[1][2] = dp[1][3] = dp[1][4] = 1;
            ll a = 0;
            For(i,3*n,4*n){
                dfs(n,i);
                a+=dp[n][i];
            }
            ll b = pow(4,n);
            ll k = gcd(a,b);
            cout<<a/k<<'/'<<b/k<<endl;
        }
    }
    return 0;
}
posted @ 2021-02-23 20:04  Paranoid5  阅读(52)  评论(0编辑  收藏  举报