题目描述:
3元买一张彩票,买一张彩票得到1,2,3,4元的概率相等。问买n次,不亏的概率多少,输出最简分数形式。
思路:
由题意我们得,这一次买彩票新出现的情况是由上次买彩票的情况分别加上1,2,3,4元得到的。于是我们可以想到使用DP来解决这道题目,状态转移方程是:
f[i][j]+=f[i-1][j-k];
其中,i 代表当前是第 i 次买彩票,j代表这次买完之后的钱数,k代表这次得到的钱。
于是,我们对彩票数由 1 ~ n 遍历,j由 0 ~ i*4 遍历,k由1到4遍历,然后把所有第n次得钱不亏的加起来,就组成了我们结果的分子。而分母很好求,就是4的n次方。
for(int i=1;i<=n;i++) { for(int j=0;j<=i*4;j++) { for(int k=1;k<=4;k++) { if(j>=k)//一定不要忘了 f[i][j]+=f[i-1][j-k]; } } }
由于他要求的是最简形式,所以我们要对分子分母求最大公因数,然后同除它,就可以得到结果。
long long gcd(long long a,long long b) { return b==0?a:gcd(b,a%b); }
完整代码:
#include<iostream> #include<cmath> using namespace std; long long f[35][130]; long long gcd(long long a,long long b) { return b==0?a:gcd(b,a%b); } int main() { int n; cin>>n; f[0][0]=1; for(int i=1;i<=n;i++) { for(int j=0;j<=i*4;j++) { for(int k=1;k<=4;k++) { if(j>=k)//一定不要忘了 f[i][j]+=f[i-1][j-k]; } } } long long cnt=0; for(int i=3*n;i<=4*n;i++) { cnt+=f[n][i]; } long long sum=pow(4,n); if(cnt==0) { puts("0/1"); } else { long long div=gcd(cnt,sum); cnt/=div; sum/=div; printf("%lld/%lld\n",cnt,sum); } return 0; }