小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); }