• AtCoder Beginner Contest 169部分题解(ATcoder)


    D - Div Game

    Solution

    对n分解质因数,设某个质因数出现的次数为cnt。每个质因数每次取得越少越好,即构成自然数列1+2+...+n,我们要找的就是最大的n使得$1+2+...+n leq cnt$,这可以二分做。

    复杂度$O(frac{sqrt{N}}{log{sqrt{N}}})$。

    Code

    #include <iostream>
    #include <cstdio>
    using namespace std;
    typedef long long ll;
    ll n, ans;
    ll f[51];
    int prime[1000010], mark[1000010], tot;
    ll find(ll x) {
        ll l = 1, r = 1000000, ret = -1;
        while (l <= r) {
            ll mid = (l + r) >> 1;
            if (mid * (mid + 1) / 2 <= x) {
                ret = mid;
                l = mid + 1;
            } else {
                r = mid - 1;
            }
        }
        return ret;
    }
    void get_prime() {
        for (int i = 2; i <= 1000000; i++) {
            if (!mark[i]) prime[++tot] = i;
            for (int j = 1; j <= tot; j++) {
                if (prime[j] * i > 1000000) break;
                mark[i * prime[j]] = 1;
                if (i % prime[j] == 0) break;
            }
        }
    }
    int main() {
        get_prime();
        for (int i = 1; i <= 50; i++) {
            f[i] = find(i);
        }
        cin >> n;
        for (int i = 1; prime[i] * prime[i] <= n && i <= tot; i++) {
            if (n % prime[i] == 0) {
                ll cnt = 0;
                while (n % prime[i] == 0) {
                    cnt++;
                    n /= prime[i];
                }
                ans += f[cnt];
            }
        }
        if (n > 1) {
            ans++;
        }
        cout << ans;
        return 0;
    }

    E - Count Median

    结论题,不会证,感性理解吧QWQ。

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <map>
    using namespace std;
    long long a[200010], b[200010];
    int n;
    int main() {
        cin >> n;
        for (int i = 1; i <= n; i++) {
            cin >> a[i] >> b[i];
        }
        sort(a + 1, a + n + 1);
        sort(b + 1, b + n + 1);
        if (n % 2) {
            cout << b[n / 2 + 1] - a[n / 2 + 1] + 1;
        } else {
            cout << b[n / 2] + b[n / 2 + 1] - a[n / 2] - a[n / 2 + 1] + 1; 
        }
        return 0;
    }

    F - Knapsack for All Subsets

    Solution

    这算是一道非常明显的背包题。

    我们可以考虑算出所有可以凑数s的集合,然后再看看它属于多少个集合。

    设$f[i][j]$代表选$i$个数,和为$j$的方案数,则答案为$sum_{i=1}^{n}f[i][s] imes 2^{n-i}$。

    有转移方程:$f[i][j]+=f[i-1][j-a[i]]$

    但是这么dp的复杂度为$O(N^2 imes S)$,显然爆炸,考虑优化。

    考虑最后答案的式子,设$g[j]=sum_{i=1}^{n}f[i][j] imes 2^{n-i}$。

    我们再来看看f的转移方程,我们发现有$g[j]+=g[j-a[i]]/2$,然后这道题就做完了。

    Code

    #include <iostream>
    #include <cstdio>
    using namespace std;
    typedef long long ll;
    const ll MOD = 998244353;
    ll n, s;
    ll a[3010];
    ll f[3010];
    ll inv2;
    ll ksm(ll aa, ll b) {
        ll ret = 1;
        while (b) {
            if (b & 1) ret = (ret * aa) % MOD;
            aa = (aa * aa) % MOD;
            b >>= 1;
        }
        return ret;
    }
    int main() {
        cin >> n >> s;
        for (ll i = 1; i <= n; i++) cin >> a[i];
        inv2 = ksm(2, MOD - 2);
        f[0] = ksm(2, n);
        for (ll i = 1; i <= n; i++) {
            for (ll k = s; k >= a[i]; k--) {
                f[k] = (f[k] + f[k - a[i]] * inv2) % MOD;//除以2等于乘以2的逆元 
            }
        }
        cout << f[s];
        return 0;
    }
  • 相关阅读:
    第06组 Alpha冲刺(4/6)
    第06组 Alpha冲刺(3/6)
    第06组 Alpha冲刺(2/6)
    第06组 Alpha冲刺(1/6)
    第06组 团队Git现场编程实战
    团队项目-需求分析报告
    团队项目-选题报告
    洛谷3195 玩具装箱(dp,斜率优化)
    CF 1334(edu85) F. Strange Function(线段树,dp)
    CF1325E. Ehab's REAL Number Theory Problem(最小环)
  • 原文地址:https://www.cnblogs.com/zcr-blog/p/13021952.html
Copyright © 2020-2023  润新知