SDUT 2022 Spring Individual Contest - L(2022江苏省赛) 补题(C、J)

C - Jump and Treasure

题意:

现在总共有从\(0,1,2.....n\),\(n+1\)个柱子,除了\(0\)号柱子,你的最远跳跃距离为\(p\),每个柱子上都有一个宝箱,宝箱的价值为\(a_i\),当你跳到\([n+1,+∞]\)时,游戏胜利,现在有\(Q\)次询问,每次询问给定一个\(x\),每次跳跃只能跳到\(x\)的倍数的柱子上,问你能否游戏胜利,胜利的话,最多能得到多少钱?

思路:

询问\(x\)时,那么可以跳的柱子为\(x,2x,3x....kx\),对于这个序列,进行\(dp\)\(f(i)\)为跳到当前柱子上能得到最多的钱数,那么对于\(dp(kx)\)的值就是\(max(dp((k-1)x,dp(k-2)x....)\),取\(max\)的大小取决于\(p\),然后就是单调队列优化这个\(dp\),如果\(x>p\)一定无法游戏胜利,直接输出不行

View Code
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 2e6 + 10;
const int inf = 1e18;
#define endl "\n"
int n, q, p;
int a[N];
int dp[N];
int vis[N];
int f[N];
int qmi(int a, int k) {
    int res = 1;
    while (k) {
        if (k & 1) res = res * a;
        k >>= 1;
        a = a * a;
    }
    return res;
}
signed main() {
    
    scanf("%lld%lld%lld",&n,&q,&p);
    for (int i = 1; i <= n; i++) {
        scanf("%lld",&a[i]);
    }
   
    int x;
    fill(dp, dp + N, -inf);
    while (q--) {
        scanf("%lld",&x);
        if (x > p) {
            puts("Noob");
        } else {
            if (vis[x]) {
                printf("%lld\n",dp[x]);
                continue;
            }
            int now = x;
            int k = x;
            deque<int> q;
            q.push_back(0);
            for (int i = x; i <= n; i += x) {
                while (q.size() && q.front() < i - p) {
                    q.pop_front();
                }
                f[i] = f[q.front()] + a[i];
                while (q.size() && f[q.back()] < f[i]) {
                    q.pop_back();
                }
                q.push_back(i);
                if (i + p > n) {
                    dp[now] = max(dp[now], f[i]);
                }
            }
            vis[now] = 1;

            printf("%lld\n",dp[now]);
        }
    }
}

J - Balanced Tree

题意:

现在定义完美二叉树为对于任何一颗子树来说,左右子树都必须是平衡的,左右子树的结点数量最多差\(1\)。现在给你\(n\)个结点,问你能够构造出多少个完美二叉树

思路:

\(f(x)\)为结点数为\(x\)能够构造出的完美二叉树的数量
\(f(x)=f(\frac{x-1}{2})^2\)\(x\)为奇数,因为此时顶点拿一个结点,现在只剩下偶数个结点,左右两边必须拿相同数量的结点,才能保证平衡
\(f(x)=2f(\frac{x}{2}-1)f(\frac{x}{2})\),\(x\)为偶数,顶点拿一个点,左奇右偶,或左偶右奇,才能保证平衡。
\(g(x)=log_2f(x)\)
那么上面的式子,就变为
\(g(x)=2g(\frac{x-1}{2} )\),\(x\)为奇数
\(g(x)=g(\frac{x}{2} )+g(\frac{x}{2}-1)+1\)
那么\(g(n)=g(n)+0g(n-1)+0\)
把上面的公式套进去进行转换
\(g(0)=0,g(1)=0\)
最终把\(g(n)=ag(1)+bg(0)+c=c\)
所以最终答案就是\(2^c\),若\(c≥64\),取模后就是0

View Code
#include <bits/stdc++.h>
using namespace std;
#define int unsigned long long
#define endl "\n"
int n;
int a, b, c;
void dfs(int x) {
    if (x <= 1) return;
    if (x & 1) {
        c += b;
        a = 2 * a + b;
        dfs((x - 1) / 2);
    } else {
        c += a;
        b = b * 2 + a;
        dfs(x / 2);
    }
}
signed main() {
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int T;
    cin >> T;

    while (T--) {
        cin >> n;
        if (n == 1 || n == 0) {
            cout << "1" << endl;
            continue;
        }
        a = 1ull, b = 0ull, c = 0ull;
        dfs(n);
        int now = c;
        if (now >= 64) {
            cout << "0" << endl;
        } else {
            int ans = 1ull << now;
            cout << ans << endl;
        }
    }
}
posted @ 2022-06-06 15:46  Wraith_G  阅读(69)  评论(0)    收藏  举报
// //