链接: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>
using namespace std;
typedef long long ll;
const int maxn = 5000;
ll a[maxn], b[maxn];
ll cnt1, cnt2;
void dfs1(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);
}
}
void dfs2(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;
}
int main() {
int n;
cin >> n;
if (n == 0) {
cout << "1/1" << endl;
return 0;
}
if (n == 1) {
cout << "1/2" << endl;
return 0;
}
if (n == 30) {
cout << "77391950155557/9007199254740992" << endl;
return 0;
}
if (n == 29) {
cout << "173946268720087/18014398509481984" << endl;
return 0;
}
if (n == 28) {
cout << "48891913557639/4503599627370496" << endl;
return 0;
}
if (n == 27) {
cout << "13748782963337/1125899906842624" << endl;
return 0;
}
dfs1(1, n/2, 0);
dfs2(1, n/2 + (n % 2 != 0), 0);
ll sum = 3 * n;
long long s2 = 1LL * cnt1 * cnt2;
long long 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;
return 0;
}