刷题记录:牛客NC23413小A买彩票

传送门:牛客

题目描述:

小A最近开始沉迷买彩票,并且希望能够通过买彩票发家致富。已知购买一张彩票需要3元,而彩票中奖的金额分别为
1,2,3,4元,并且比较独特的是这个彩票中奖的各种金额都是等可能的。现在小A连续购买了n张彩票,他希望你能够告
诉他至少能够不亏本的概率是多少。
输入:
2
输出:
3/8

一道线性dp题

主要思路:

  1. 观察这道题,我们能有一个比较显然的想法,我们可以使用dp[i][j]来记录买了第i张彩票赚了j块钱的次数(注意,是次数).那么显然的我们的最终答案就应该是
ll ans=0;ll ans2=0;
for(int i=n;i<=4*n;i++) {
   	ans+=dp[n][i];
   	if(i>=3*n) {
   		ans2+=dp[n][i];
   	}
}
ANS=ans/ans2

因为我们的ans记录的是所有的金额的次数,而我们的ans2记录的是所有的不亏钱的金额的次数

  1. 接下来需要做的就是如何推出这个转移关系了,其实这个转移方程也十分的简单,假设我们现在枚举到的金额为j,那么显然的我们可以由之前的j-1,j-2,j-3,j-4转移过来,因为彩票一次只能增加[1,4],当然我们的j减去1,2,3,4之后应该大于我们的i-1,因为前i-1张彩票至少是可以赚i-1块钱的.

最后总结一下我们的dp方程

dp[i][j]+=(dp[i-1][j-k]) k ∈ \in [ 1 , 4 ] [1,4] [1,4] , , , j − k > = i − 1 j-k>=i-1 jk>=i1

至于我们的既约分数的形式,我们直接使用gcd求出最小公约数即可

下面是具体的代码部分:

#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <vector>
#include <map>
#include <set>
#include <queue>
#include <string.h>
#include <stack>
#include <deque>
using namespace std;
typedef long long ll;
#define inf 0x3f3f3f3f
#define root 1,n,1
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
inline ll read() {
	ll x=0,w=1;char ch=getchar();
	for(;ch>'9'||ch<'0';ch=getchar()) if(ch=='-') w=-1;
	for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0';
	return x*w;
}
#define maxn 1000000
#define ll_maxn 0x3f3f3f3f3f3f3f3f
const double eps=1e-8;
int n;ll dp[1000][1000];
ll gcd(ll a,ll b) {
	if(b==0) return a;
	else return gcd(b,a%b);
}
int main() {
	n=read();
	dp[1][1]=1,dp[1][2]=1;dp[1][3]=1;dp[1][4]=1;
	for(int i=2;i<=n;i++) {
		for(int j=i;j<=4*i;j++) {
			if(j-1>=i-1) dp[i][j]+=dp[i-1][j-1];
			if(j-2>=i-1) dp[i][j]+=dp[i-1][j-2];
			if(j-3>=i-1) dp[i][j]+=dp[i-1][j-3];
			if(j-4>=i-1) dp[i][j]+=dp[i-1][j-4];
		}
	}
	ll ans=0;ll ans2=0;
	for(int i=n;i<=4*n;i++) {
		ans+=dp[n][i];
		if(i>=3*n) {
			ans2+=dp[n][i];
		}
	} 
	if(ans==0) cout<<"1/1"<<endl;
	else {
		ll _gcd=gcd(ans,ans2);
		cout<<ans2/_gcd<<"/"<<ans/_gcd<<endl;
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值