• 2018-2019 ACM-ICPC, Asia East Continent Finals 补题


    想趁着大家都有空的时间多练几场,队友上来就挑了一场ec-final,只能说与我的水平不太符合

    尽力补题中。

    I Misunderstood … Missing

    挺有意思的签到题,一个人还没想出来。

    因为前面的状态会对后面的状态产生影响,后面的状态不会对前面的决策产生影响,所以倒着dp。

    考虑将答案组成的形式拆开,设(f(i, j))表示第(i)轮结束之后后面还要攻击(j)轮的答案,如果我们进行一个攻击力(+b_i)的操作,后面会有(jb_i)的贡献;如果我们进行一次攻击,后面会有(a_i)的贡献。

    最后考虑这个加差值的操作,如果后面是在(x_{p_1}, x_{p_2}, cdots, x_{p_j})的位置攻击,贡献为(sum (x_{p_k} - i) = sum x - j * i)。于是再增加一维,设(f(i, j, k))表示第(i)轮结束之后,后面攻击了(j)次,后面攻击的回合数标号之和为(k)的最大伤害。枚举状态需要(O(n^4)),转移(O(1))

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    typedef double db;
    typedef pair <int, int> pin;
    
    #ifndef ONLINE_JUDGE
    bool MEMORY_ST;
    #endif
    
    const int N = 105;
    const int M = 5050 + 5;
    const ll P = 998244353LL;
    
    int T, n;
    ll a[N], b[N], c[N], f[2][N][M];
    
    namespace Fread {
        const int L = 1 << 15;
        
        char buffer[L], *S, *T;
        
        inline char Getchar() {
            if(S == T) {
                T = (S = buffer) + fread(buffer, 1, L, stdin);
                if(S == T) return EOF;
            }
            return *S++;
        }
        
        template <class T> 
        inline void read(T &X) {
            char ch; T op = 1;
            for(ch = Getchar(); ch > '9' || ch < '0'; ch = Getchar())
                if(ch == '-') op = -1;
            for(X = 0; ch >= '0' && ch <= '9'; ch = Getchar()) 
                X = (X << 1) + (X << 3) + ch - '0'; 
            X *= op;
        }
        
    } using Fread::read;   
    
    inline void chkMax(ll &x, ll y) {
        if (y > x) x = y;
    }
    
    #ifndef ONLINE_JUDGE
    bool MEMORY_ED;
    #endif
    
    int main() {
    #ifndef ONLINE_JUDGE
        freopen("sample.in", "r", stdin);
        clock_t st_clock = clock();
    #endif
    
        read(T);
        for (; T--; ) {
            read(n);
            for (int i = 1; i <= n; i++) read(a[i]), read(b[i]), read(c[i]);
            int sum = (n + 1) * n / 2;
            for (int i = 0; i < 2; i++)
                for (int j = 0; j <= n; j++)
                    for (int k = 0; k <= sum; k++)
                        f[i][j][k] = -1;
            f[n & 1][0][0] = 0;
            for (int i = n; i >= 1; i--) {
                int cur = i & 1, suc = cur ^ 1;
                for (int j = 0; j <= n; j++)
                    for (int k = 0; k <= sum; k++)
                        f[suc][j][k] = -1;
                for (int j = 0; i + j <= n; j++) {
                    for (int k = 0; k <= sum; k++) {
                        if (f[cur][j][k] == -1) continue;
                        chkMax(f[suc][j + 1][k + i], f[cur][j][k] + a[i]);
                        chkMax(f[suc][j][k], f[cur][j][k] + b[i] * (k - i * j));
                        chkMax(f[suc][j][k], f[cur][j][k] + c[i] * j);
                    }
                }
            }
            ll ans = 0;
            for (int j = 0; j <= n; j++)
                for (int k = 0; k <= sum; k++)
                    ans = max(ans, f[0][j][k]);
            printf("%lld
    ", ans);
        }
    
    #ifndef ONLINE_JUDGE
        clock_t ed_clock = clock();
        printf("time = %f ms
    ", (double)(ed_clock - st_clock) / CLOCKS_PER_SEC * 1000);
        printf("memory = %.2f MB
    ", (&MEMORY_ED - &MEMORY_ST) / 1024.0 / 1024.0);
    #endif
        return 0;
    }
    

    jls说这就是slay the spire的力量战,恶魔形态是不是太拉了一点……

    C Heretical … Möbius

    很好玩的题,感觉那个年代的人都很喜欢出这种风格的题目。

    题目中的(|mu(n)|)只跟(n)是否含有平方因子有关,我们不妨考虑一个最小的完全平方数(4),那么(4)的倍数所在的位置一定是(0),据此我们可以进行可行性检验,先枚举(ans mod 4)的位置,然后看看这些位数是不是都是(0)

    如果某个余数(r)可行,那么相当于我们得到了一个可选的同余方程:

    [ans equiv -r mod p ]

    为什么是可选的?因为对于模数(4)我们可能可以找到多个位置可行。

    同理,考虑(200)以内的质数的平方,可以用的有(6)(4, 9, 25, 49, 121, 169),分别检验出可行的余数,然后我们考虑枚举一下这些余数,根据中国剩余定理,我们可以合并出一个在([0, 901800900))的满足条件的数(x),然后我们考虑检验这个(x)(x + 901800900)是否可以作为答案。

    怎么检验呢?枚举([1, sqrt{10^9}])以内的质数,用这些质数暴力地去这个区间里面分解质因子,一次检验的时间为(O(frac{sqrt{Maxn}}{log Maxn} + 200 log n)),后面那个大概是一个区间内因子总数。

    卡时出解即可。

    对于做题的人来说,工作到这里已经结束了;但是对于出题人来说,还需要保证自己造出来的数据是正确的,也不知道jls是怎么完成这项工作的,好在这个(10^9)也不是很大。

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    typedef double db;
    typedef pair <int, int> pin;
    
    #ifndef ONLINE_JUDGE
    bool MEMORY_ST;
    #endif
    
    const int N = 205;
    const int M = 35005;
    const int Maxm = 35000;
    const int P[] = {4, 9, 25, 49, 121, 169};
    const int inf = 1e9;
    
    int ans = inf + 5, a[N], pcnt, pri[M];
    bool vis[M], returnFlag = 0;
    char s[N];
    vector <int> vec[6], rest;
    clock_t stClock;
    
    inline void sieve() {
        for (int i = 2; i <= Maxm; i++) {
            if (!vis[i]) {
                pri[++pcnt] = i;
            }
            for (int j = 1; j <= pcnt && i * pri[j] <= Maxm; j++) {
                vis[i * pri[j]] = 1;
                if (i % pri[j] == 0) break;
            }
        }
    }
    
    inline bool chk(int p, int len) {
        for (int i = p; i < 200; i += len)
            if (a[i] != 0)
                return 0;
        return 1;
    }
    
    ll exgcd(ll ca, ll cb, ll &x, ll &y) {
        if (!cb) {
            x = 1, y = 0;
            return ca;
        }
        ll d = exgcd(cb, ca % cb, y, x);
        y -= ca / cb * x;
        return d;
    }
    
    inline int mergeCrt() {
        ll prod = 1, res = 0;
        for (int i = 0; i < 6; i++) prod = prod * (1LL * P[i]);
        // printf("%lld
    ", prod);
        for (int i = 0; i < 6; i++) {
            ll t = prod / P[i], it, y;
            exgcd(t, P[i], it, y);
            res = (res + 1LL * rest[i] * t % prod * it % prod) % prod;
        }
        return (res % prod + prod) % prod;
    }
    
    inline bool chkAns(int cur) {
        if (cur == 0) return 0;
        vector <int> b(200), c(200);
        for (int i = 0; i < 200; i++) {
            b[i] = cur + i;
            c[i] = 1;
        } 
        for (int i = 1; i <= pcnt; i++) {
            int cp = pri[i];
            int st = (cur + cp - 1) / cp * cp;
            if (st - cur > 199) continue;
            for (int j = st; j < cur + 200; j += cp) {
                assert(b[j - cur] % cp == 0);
                int cnt = 0;
                for (; b[j - cur] % cp == 0; b[j - cur] /= cp, ++cnt);
                if (cnt >= 2) c[j - cur] = 0;
            } 
        }
        for (int i = 0; i < 200; i++)
            if (c[i] != a[i])
                return 0;
        return 1;
    }
    
    inline void up() {
        int cur = mergeCrt();
        // assert(cur >= 1);
        if (cur + 200 - 1 > inf) return;
        if (chkAns(cur)) ans = min(ans, cur);
        if (1LL * cur + 901800900LL + 200 - 1 > inf) return; 
        cur += 901800900;
        if (chkAns(cur)) ans = min(ans, cur);
    }
    
    void dfs(int p) {
        if (returnFlag) return;
        clock_t curClock = clock();
        if ((db) (curClock - stClock) > 0.9 * CLOCKS_PER_SEC) {
            returnFlag = 1;
            return;
        }
        if (p == 6) {
            up();
            return;
        }
        if (vec[p].empty()) return;
        for (int i = 0; i < vec[p].size(); i++) {
            rest.emplace_back(vec[p][i]);
            dfs(p + 1);
            rest.pop_back();
        }
    }
    
    #ifndef ONLINE_JUDGE
    bool MEMORY_ED;
    #endif
    
    int main() {
    #ifndef ONLINE_JUDGE
        freopen("sample.in", "r", stdin);
        clock_t st_clock = clock();
    #endif
    
        stClock = clock();
        sieve();
        // for (int i = 1; i <= 20; i++)
        //     printf("%d
    ", pri[i]);
        int cnt = 0;
        for (int i = 1; i <= 10; i++) {
            scanf("%s", s);
            for (int j = 0; j < 20; j++) a[cnt++] = s[j] - '0';
        }
        for (int i = 0; i < 6; i++) {
            for (int j = 0; j < P[i]; j++) {
                if (chk(j, P[i])) {
                    vec[i].emplace_back((P[i] - j) % P[i]);
                }
            }
        }
        dfs(0);
        printf("%d
    ", ans == inf + 5 ? -1 : ans);
    
    #ifndef ONLINE_JUDGE
        clock_t ed_clock = clock();
        printf("time = %f ms
    ", (double)(ed_clock - st_clock) / CLOCKS_PER_SEC * 1000);
        printf("memory = %.2f MB
    ", (&MEMORY_ED - &MEMORY_ST) / 1024.0 / 1024.0);
    #endif
        return 0;
    }
    
  • 相关阅读:
    获取Enum枚举值描述的几法方法
    Android开发入门 Button事件实现的方法(原创)
    最有价值的.Net第三方控件
    Eclipse快捷键大全(转载)
    recovery教程
    XP系统通过无线网卡共享宽带给其他设备,正确的共享设置(修正版,绝对可行)
    使用Eclipse写QT
    Android 4.0模拟器弹出“谷歌拼音输入法”已停止运行的解决方法
    C# 枚举用法总结
    谷歌安卓系统使用必读,什么是root, Recovery, Radio, APP TO SD, Rom
  • 原文地址:https://www.cnblogs.com/CzxingcHen/p/15418410.html
Copyright © 2020-2023  润新知