链接:https://ac.nowcoder.com/acm/contest/549/C
来源:牛客网
小A最近开始沉迷买彩票,并且希望能够通过买彩票发家致富。
已知购买一张彩票需要3元,而彩票中奖的金额分别为1,2,3,4元,并且比较独特的是这个彩票中奖的各种金额都是等可能的。
现在小A连续购买了n张彩票,他希望你能够告诉他至少能够不亏本的概率是多少。
思路一:暴力搜索+打表,将n张彩票分一半进行购买。dfs枚举两半得到a数组和b数组,最后枚举a,二分b判断有多少个满足条件
时间复杂度 O(2^(n)*log(2^(n)),时间爆炸了,所以20-30打表
#include<bits/stdc++.h>usingnamespace std;typedeflonglong ll;constint maxn =5000;
ll a[maxn], b[maxn];
ll cnt1, cnt2;voiddfs1(int k,int len,int sum){if(k > len){
a[sum]++;
cnt1++;return;}for(int i =1; i <=4; i++){dfs1(k +1, len,sum + i);}}voiddfs2(int k,int len,int sum){if(k > len){
cnt2++;
b[sum]++;return;}for(int i =1; i <=4; i++){dfs2(k +1, len, sum + i);}}
ll gcd(ll a, ll b){return b ?gcd(b, a % b): a;}intmain(){int n;
cin >> n;if(n ==0){
cout <<"1/1"<< endl;return0;}if(n ==1){
cout <<"1/2"<< endl;return0;}if(n ==30){
cout <<"77391950155557/9007199254740992"<< endl;return0;}if(n ==29){
cout <<"173946268720087/18014398509481984"<< endl;return0;}if(n ==28){
cout <<"48891913557639/4503599627370496"<< endl;return0;}if(n ==27){
cout <<"13748782963337/1125899906842624"<< endl;return0;}dfs1(1, n/2,0);dfs2(1, n/2+(n %2!=0),0);
ll sum =3* n;longlong s2 =1LL* cnt1 * cnt2;longlong s1 =0;for(int i =1; i <= sum; i++){for(int j =1; j <=120; j++){if(i + j >= sum){
s1 +=1LL* a[i]* b[j];}}}
ll d =gcd(s1, s2);
cout << s1 / d <<"/"<< s2 / d << endl;return0;}
思路二:dp。
作者:西格玛象限
链接:https://ac.nowcoder.com/discuss/177449?type=101&order=0&pos=7&page=1
来源:牛客网
考虑买n张彩票的总的方案数是
4^n,然后统计不亏本的方案数,记录
f[i][j]是买到第i张彩票总获利为j的总方案数。
f[i][j]=∑f[i−1][j−k],k=1,2,3,4,最后统计一下不亏本的方案数即可。由于数据规模很小,考虑分别组合枚举有多少个1,2,3,4也可以通过。
#include<bits/stdc++.h>usingnamespace std;constint maxn =200;longlong dp[maxn][maxn];typedeflonglong ll;
ll gcd(ll a, ll b){return b ?gcd(b, a % b): a;}intmain(){int n;
cin >> n;
dp[0][0]=1;for(int i =1; i <= n; i++){for(int j =1; j <=120; j++){for(int k =1; k <=4; k++){if(j >= k){
dp[i][j]+= dp[i -1][j - k];}}}}longlong a =0;longlong b =pow(4, n);for(int i =3* n; i <=120; i++){
a += dp[n][i];}longlong d =gcd(a, b);
cout << a / d <<"/"<< b / d << endl;return0;}