牛客小白月赛13 C题

链接: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;
}

思路二: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 ,最后统计一下不亏本的方案数即可。由于数据规模很小,考虑分别组合枚举有多少个1234也可以通过。

#include <bits/stdc++.h>
using namespace std;
const int maxn = 200;
long long dp[maxn][maxn];
typedef long long ll;
ll gcd(ll a, ll b) {
    return b ? gcd(b, a % b) : a;
}
 
int main() {
    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];
                }
            }
        }
    }
    long long a = 0;
    long long b = pow(4, n);
    for (int i = 3 * n; i <= 120; i++) {
        a += dp[n][i];
    }
    long long d = gcd(a, b);
    cout << a / d << "/" << b / d << endl;
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_37520038/article/details/89356753
今日推荐