小A买彩票

来源:牛客网

题目描述
小A最近开始沉迷买彩票,并且希望能够通过买彩票发家致富。已知购买一张彩票需要3元,而彩票中奖的金额分别为1,2,3,4元,并且比较独特的是这个彩票中奖的各种金额都是等可能的。现在小A连续购买了n张彩票,他希望你能够告诉他至少能够不亏本的概率是多少。
输入描述:
一行一个整数N,为小A购买的彩票数量一行一个整数N,为小A购买的彩票数量
输出描述:
输出一个最简分数a/b,表示小A不亏本的概率。
\若概率为1,则输出1/1,概率为0,则输出0/1。输出一个最简分数a/b,表示小A不亏本的概率。
若概率为1,则输出1/1,概率为0,则输出0/1。
示例1
输入
复制
2
输出
复制
3/8
备注:
0≤n≤30

题意很简单就是:花3元买彩票,彩票可能是1,2,3,4;问买n张彩票不亏本的概率多大(最简分数)

题解:知识点:DP枚举
首先我们要得到的是不亏本的概率:不亏本的数量总数量\frac{不亏本的数量}{总数量}
所以我们把问题转化成不亏本的数量和总数量。
总数量好说就是类似2进制枚举的总可能性。也就是4n4^{n}4n 。
不亏本的数量:首先不亏本的范围是3 * n~4 * n,就是用二维DP(i,j)来表示,i表示第几个 j表示多少钱 。所以i是(1 ~ n),到达每个i时可能会有(i ~ 4* i)这么多钱,所以j的范围是(i ~ 4* i);
状态转移方程:dp[i][j]=dp[i-1][j-1]+dp[i-1][j-2]+dp[i-1][j-3]+dp[i-1][j-4];
dp(i,j)状态可以从上一个(dp(i-1,x))转移过来也就是,上一个可以买到(1/2/3/4)变成dp(i,j).
最后扫一遍(3n~4n)总数量就是不亏本的数量。

#include<iostream>
#include<algorithm>
#include<map>
#include<string> 
#include <math.h> 
#include<memory.h>
#include<cstring>
#include<bits/stdc++.h> 
using namespace std;
typedef long long ll; 
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
const int INF=0x3f3f3f3f;
const int maxn=1e4+100;
const int maxa=1e9+10;
ll dp[50][maxn];
ll ans,sum;
ll qpow(ll a,ll b){
    ll sum=1;
    while(b){
       if(b&1) sum=sum*a;
        b>>=1;
        a=a*a;
    }
    return sum;
}
ll gcd(ll a,ll b){
    if(b==0){
        return a;
    }
    return gcd(b,a%b);
}
int main(){
    int n;
    cin>>n;
    dp[0][0]=1;
    for(int i=1;i<=n;i++)
        for(int j=i;j<=i*4;j++)
            dp[i][j]=dp[i-1][j-1]+dp[i-1][j-2]+dp[i-1][j-3]+dp[i-1][j-4];//这个状态可以从这次四个继承过来 
 
    sum=qpow(4,n); //总的可能性 就是4^n
    for(int i=3*n;i<=n*4;i++)
        ans+=dp[n][i];//不亏本的可能性;
    ll g=gcd(ans,sum);
    printf("%lld/%lld\n",ans/g,sum/g);
}

 

posted @ 2021-03-09 16:42  lipu123  阅读(137)  评论(0编辑  收藏  举报