• 2021"MINIEYE杯"中超(5)补题


    2021"MINIEYE杯"中超(5)

    1004 Another String

    维护这么一个数组:f[i, j]表示以i,j为起点的两个子序列可以满足条件的最大长度。那么当t在i ~ i + f[i, j]这个区间时,f[i, j]对答案是有贡献的。当t在j及以后时,f[i, j]对答案是没有贡献的。所以我们可以在求出f[i, j]后,维护一个差分矩阵。对于每个f[i, j],ans[i] ++ , ans[i + f[i,j]] -- ;这表示在这个范围内f[i, j]的贡献,同时当分割点大于等于j时是没有贡献的。所以我们还要有 ans[j] -= f[i, j],ans[j + 1] += f[i, j]来消除此部分的贡献。

    最后取两次前缀和即可得到答案。

    #include <bits/stdc++.h>
    
    using namespace std;
    
    const int N = 3010;
    
    int t;
    int f[N][N];//f[i][j]表示以i,j为起点的两个子序列满足条件的最大长度
    int n, k;
    char s[N];
    int ans[N];
    
    void solve()
    {
        cin >> n >> k;
        cin >> (s + 1);
        
        //尺取
        for (int l = 2; l <= n; l ++ )//枚举右端点
        {
            int len = 0, dif = 0;//len为当前满足的最长区间长度,dif为当前不同的位置有多少个
            for (int i = 1, j = l; j <= n; i ++ , j ++ )//从两个区间的起点开始扫两个子序列
            {
                while (dif <= k)//当满足条件的话继续往后移动
                {
                    dif += (s[i + len] != s[j + len]);
                    len ++ ;
                }
                f[i][j] = min(len - 1, min(j - i, n - j + 1));//更新f[i][j]
                len -- ;//后移一位
                dif -= (s[j] != s[i]);
            }
        }
        
        memset(ans, 0, sizeof ans);
        //差分矩阵更新
        for (int i = 1; i <= n; i ++ )
            for (int j = i + 1; j <= n; j ++ )
            {
                ans[i] ++ ; ans[i + f[i][j]] -- ;
                ans[j] -= f[i][j]; ans[j + 1] += f[i][j];
            }
        for (int i = 1; i <= n; i ++ ) ans[i] += ans[i - 1];
        for (int i = 1; i <= n; i ++ ) ans[i] += ans[i - 1];
        for (int i = 1; i < n; i ++ ) cout << ans[i] << endl;
    }
    
    int main()
    {
        ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
        cin >> t;
        while (t -- ) solve();
        return 0;
    }
    
    1006 Cute Tree

    模拟

    #include <bits/stdc++.h>
    
    using namespace std;
    
    const int N = 2e5 + 10;
    
    int t;
    int n;
    int a[N];
    struct node
    {
        int a[3];
    }tr[N << 2];
    int cnt;
    
    void build(int ro, int l, int r)
    {
        if (l == r) return;
        if (r == l + 1)
        {
            build(tr[ro].a[0] = ++ cnt, l, l);
            build(tr[ro].a[1] = ++ cnt, r, r);
        }
        else
        {
            int k = (r - l) / 3 + 1;
            int b = l + k - 1;
            int c = b + r >> 1;
            build(tr[ro].a[0] = ++ cnt, l, b);
            build(tr[ro].a[1] = ++ cnt, b + 1, c);
            build(tr[ro].a[2] = ++ cnt, c + 1, r);
        }
    }
    
    int main()
    {
        scanf("%d", &t);
        while (t -- )
        {
            scanf("%d", &n);
            for (int i = 1; i <= n; i ++ ) scanf("%d", &a[i]);
            cnt = 1;
            build(1, 1, n);
            printf("%d
    ", cnt);
        }
        return 0;
    }
    
    1007 Banzhuan

    比赛时由于我的原因想错了最优情况,导致思路错误,没有过掉题。。。

    最大情况:往第n层放满,然后让它掉下去,放n次。

    最小情况:XOY,XOZ,YOZ层放满。

    比较坑的地方就是取模操作,由于有除法,直接相除取模会导致错误,所以要用到逆元。我们可以快速幂求得逆元。

    #include <bits/stdc++.h>
    
    using namespace std;
    
    typedef long long LL;
    
    const LL MOD = 1e9 + 7;
    
    int t;
    LL n;
    
    LL qmi(LL a, LL k)//快速幂求逆元
    {
        LL res = 1;
        while (k)
        {
            if (k & 1) res = (LL)res * a % MOD;
            k >>= 1;
            a = (LL)a * a % MOD;
        }
        return res;
    }
    
    void solve()
    {
        cin >> n; n %= MOD;
        LL a, b, c;
        a = (n % MOD * n % MOD) * (n + 1) % MOD * (n + 1) % MOD * (2 * n + 1) % MOD * qmi(12,MOD - 2) % MOD;
        b = (n - 1) % MOD * (n - 1) % MOD * (n + 2) % MOD * (n + 2) % MOD * qmi(4,MOD - 2) % MOD;
        c = (n - 1) % MOD * n % MOD * (n + 1) % MOD * (n + 2) % MOD * (2 * n + 1) % MOD * qmi(12,MOD-2) % MOD - (n + 2) % MOD * (n - 1) % MOD * qmi(2,MOD - 2)%MOD;
        LL r1 = ((a + b + c) % MOD + MOD) % MOD;
        LL r2 = n * n % MOD * n % MOD * (n + 1) % MOD * (n + 1) % MOD * (2 * n + 1) % MOD * qmi(12, MOD - 2) % MOD * n % MOD;
        cout << r1 << endl << r2 << endl;
    }
    
    int main()
    {
        cin >> t;
        while (t -- ) solve();
        return 0;
    }
    
    
  • 相关阅读:
    Python pip命令
    Linux extundelete命令
    Ruby Gem命令
    RPM包制作方法
    Openssl genpkey命令
    Linux ssldump命令
    openssl 证书操作命令
    Linux下使用openssl生成证书
    Volley框架载入网络图片
    Gmail上不去怎么办?
  • 原文地址:https://www.cnblogs.com/scl0725/p/15135593.html
Copyright © 2020-2023  润新知