AcWing:5057. 截断数组+5058. 双色球- 前缀和 和 DP

5057. 截断数组
可以在输入数据后就对p进行取模操作

#include 
using namespace std;
#define ll long long
#define sf(x) scanf("%d", &x);
#define de(x) cout << x << " ";
#define Pu puts("");
const int N = 1e5 + 9;
int n, m, ans;
int p;
int pre[N];  // 前缀和
int main() {
    cin >> n >> p;
    int x;
    int sz = 0;  // 总和
    for (int i = 1; i <= n; i++) {
        cin >> x;
        x %= p;
        pre[i] = (pre[i - 1] + x) % p;
        sz = (sz + x) % p;
    }
    ans = 0;
    for (int i = 2; i <= n; i++) {
        ans = max(ans, (pre[i - 1] + (sz + p - pre[i - 1]) % p));
    }
    de(ans);
    return 0;
}

5058. 双色球
思路见注释

#include 
using namespace std;
#define ll long long
#define sf(x) scanf("%d", &x);
#define de(x) cout << x << " ";
#define Pu puts("");
const int N = 1e3 + 9;
int n, m;
double f[N][N];  // f[i][j]表示剩下i个白球和j个黑球时,赢的概率
int main() {
    cin >> n >> m;
    for (int i = 1; i <= n; i++)
        f[i][0] = 1;  // 只剩下白球,且轮到约翰拿
    for (int j = 1; j <= m; j++)
        f[0][j] = 0;  // 只剩下黑球,那么两个人会一直拿直到空,会输
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
            // 思路参考闫总题解视频
            // https://www.acwing.com/video/4835/
            double p1 = i * 1.0 / (i + j);
            double p2 = j * 1.0 / (i + j) * (j - 1) / (i + j - 1);
            double p3 = 0, p4 = 0;
            if (j >= 3) {
                p3 = p2 * (j - 2) / (i + j - 2) * f[i][j - 3];
            }
            if (j >= 2) {
                p4 = p2 * i / (i + j - 2) * f[i - 1][j - 2];
            }
            f[i][j] = p1 + p3 + p4;
        }
    }
    printf("%.10lf\n", f[n][m]);
    return 0;
}

你可能感兴趣的:(AcWing,#,思维+模拟,刷题+算法,算法)