zoukankan      html  css  js  c++  java
  • ZR18提高5解题报告

    不想说啥了,比赛期间智商全程下线

    A

    设$f[i][j]$表示前$i$个位置,前缀和为$j$的方案数,转移的时候该位置放了什么,以及该位置之前的和是多少。

    发现第二维可以前缀和优化。

    不用管代码里的fib是什么,当时傻了在xjb分析下界。。。。

    时间复杂度:$O(nk)$

    /*
    
    */
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<map>
    #include<vector>
    #include<set>
    #include<queue>
    #include<cmath>
    //#include<ext/pb_ds/assoc_container.hpp>
    //#include<ext/pb_ds/hash_policy.hpp>
    #define Pair pair<int, int>
    #define MP(x, y) make_pair(x, y)
    #define fi first
    #define se second
    #define int long long 
    #define LL long long 
    #define ull unsigned long long 
    #define rg register 
    #define pt(x) printf("%d ", x);
    //#define getchar() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1<<22, stdin), p1 == p2) ? EOF : *p1++)
    //char buf[(1 << 22)], *p1 = buf, *p2 = buf;
    //char obuf[1<<24], *O = obuf;
    //void print(int x) {if(x > 9) print(x / 10); *O++ = x % 10 + '0';}
    //#define OS  *O++ = ' ';
    using namespace std;
    //using namespace __gnu_pbds;
    const int MAXN = 1e6 + 10, INF = 1e9 + 10, mod = 998244353;
    const double eps = 1e-9;
    inline int read() {
        char c = getchar(); int x = 0, f = 1;
        while(c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();}
        while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
        return x * f;
    }
    int f[21][MAXN], s[MAXN], fib[MAXN];
    main() {
        int N = read(), K = read();//k个位置 总和为n 
        fib[1] = 1; fib[2] = 1;
        for(int i = 3; i <= N; i++) fib[i] = fib[i - 1] + fib[i - 2];
        for(int i = 1; i <= N; i++) f[1][i] = 1, s[i] = (s[i - 1] + f[1][i]) % mod;
        for(int i = 2; i <= K; i++) {
            for(int j = 1; j <= N; j++) {
            //    for(int k = fib[i - 1]; k <= j / 2; k++) (f[i][j] += f[i - 1][k]) %= mod;
                f[i][j] = s[j / 2] % mod;
                if((j / 2 >= fib[i - 1]) && (fib[i - 1] >= 1)) f[i][j] = (f[i][j] - s[fib[i - 1] - 1] + mod) % mod;            
            }
            s[0] = 0;
            for(int j = 1; j <= N; j++) 
                s[j] = (s[j - 1] + f[i][j]) % mod;
        }
    
        printf("%d", f[K][N] % mod);
        return 0;
    }
    /*
    15 3
    */
    A

    B

    起点和终点都是已知的,那么对于其他的节点,一定是从根节点走到该节点再往回走。

    这样我们记录下根节点到其他节点路径的并,在这之中唯一不需要经过两次的是该节点到根的路径,减去即可

    由于每个点只会经过一次,因此时间复杂度为:$O(n+m)$

    #include<bits/stdc++.h>
    using namespace std;
    const int MAXN = 1e5 + 10;
    inline int read() {
        char c = getchar(); int x = 0, f = 1;
        while(c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();}
        while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
        return x * f;
    }
    int N, M, dep[MAXN], fa[MAXN], vis[MAXN];
    vector<int> v[MAXN];
    void dfs(int x, int _fa) {
        dep[x] = dep[_fa] + 1;
        fa[x] = _fa;
        for(int i = 0; i < v[x].size(); i++) {
            int to = v[x][i];
            if(to == _fa) continue;
            dfs(to, x);
        }
    }
    int main() {
        N = read(); M = read();
        for(int i = 1; i <= N - 1; i++) {
            int x = read(), y = read();
            v[x].push_back(y); v[y].push_back(x);
        }
        dep[0] = -1; dfs(1, 0);
        vis[1] = 1;
        int tot = 0, ans = 0;
        for(int i = 1; i <= M; i++) {
            int x = read(), tmp = x;
            while(!vis[x]) tot++, vis[x] = 1, x = fa[x];
            printf("%d
    ", 2 * tot - dep[tmp]);
        }
        return 0;
    }
    /*
    */
    B

    C

    神仙题Orz

    题目里有个很良心的部分分

    这就提示我们跟二进制拆分有点关系了

    序列上的问题好像很难搞,我们扔到环上去(这是怎么想到的啊Orz)

    构造一个这样的环

    上下两个$0$不管进化几次肯定都是$0$(左右对称)

    考虑其他位置,观察每一项展开后的式子不难发现(发现不了。。)

    对于位置$i$,如果$a[i]$进化了$2^d$后变为$c[i]$,那么$c[i] = a[i - 2^d] + a[i+2^d]$

    做完了。。

    #include<cstdio>
    #include<cstring>
    #define int long long 
    using namespace std;
    const int MAXN = 1e6 + 10;
    inline int read() {
        char c = getchar(); int x = 0, f = 1;
        while(c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();}
        while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
        return x * f;
    }
    int T, N;
    char s[MAXN];
    int a[MAXN], b[MAXN];
    main() {
        T = read(); N = read();
        // for(int i = 1; i <= N; i++) a[i] = read();
        scanf("%s", s + 1);
        for(int i = 1; i <= N; i++) a[i] = s[i] - '0', a[N * 2  + 2 - i] = a[i]; 
        N = N * 2 + 2;
        for(int j = 61; j >= 0; j--) {
            if(T & (1ll << j)) {
                int base = (1ll << j) % N;
                for(int i = 0; i <= N; i++) b[i] = a[(i - base + N) % N] ^ a[(i + base) % N];
                memcpy(a, b, sizeof(a));
            }
        }
        for(int i = 1; i <= N / 2 - 1; i++) printf("%d", a[i]);
        return 0;
    }
    /*
    2 5
    10010
    */
    C
  • 相关阅读:
    链路的有效性检测 及 基于TCP的通信为什么需要RETRY
    python join
    协程
    python socket 选项
    Spring @Resource、@Autowired、@Qualifier的区别
    maven插件
    代码中的特殊注释
    AOP 底层技术比较
    关于Android开发中的证书和密钥等问题
    tomcat部署web项目的3中方法
  • 原文地址:https://www.cnblogs.com/zwfymqz/p/9698200.html
Copyright © 2011-2022 走看看