zoukankan      html  css  js  c++  java
  • AtCoder Regular Contest 99

    传送门

    C - Minimization

    第一次可能有多种选择,我们枚举所有的选择,然后两边贪心取即可。

    Code
    #include <bits/stdc++.h>
    #define MP make_pair
    #define fi first
    #define se second
    #define sz(x) (int)(x).size()
    //#define Local
    using namespace std;
    typedef long long ll;
    typedef pair<int, int> pii;
    const int N = 1e5 + 5;
    
    int n, k;
    
    void run() {
        int p;
        for(int i = 1; i <= n; i++) {
            int x; cin >> x;
            if(x == 1) p = i;
        }
        int ans = N;
        for(int i = 1; i <= n; i++) {
            int l = i, r = min(n, i + k - 1);
            if(l <= p && p <= r)
                ans = min(ans, 1 + (l - 1 + k - 2) / (k - 1) + (n - r + k - 2) / (k - 1));
        }
        cout << ans << '
    ';
    }
    
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(0); cout.tie(0);
        cout << fixed << setprecision(20);
    #ifdef Local
        freopen("../input.in", "r", stdin);
        freopen("../output.out", "w", stdout);
    #endif
        while(cin >> n >> k) run();
        return 0;
    }
    
    

    D - Snuke Numbers

    这个就是打表找规律...但规律也不是很好找,这个规律是变换的规律,可能一次加上(10^i),也可以加上(10^{i+1}),两个判断一下即可。

    Code
    #include <bits/stdc++.h>
    #define MP make_pair
    #define fi first
    #define se second
    #define sz(x) (int)(x).size()
    #define Local
    using namespace std;
    typedef long long ll;
    typedef pair<int, int> pii;
    const int N = 1e5 + 5;
    
    int K;
    
    double Snuke(ll x) {
        ll tmp = 0, c = x;
        while(c) {
            tmp += c % 10;
            c /= 10;
        }
        return 1.0 * x / tmp;
    }
    
    void run() {
        ll res = 0, x = 1;
        while(K--) {
            double t1, t2;
            while(true) {
                t1 = Snuke(res + x), t2 = Snuke(res + x * 10);
                if(t1 <= t2) break;
                x *= 10;
            }
            res += x;
            cout << res << '
    ';
        }
    }
    
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(0); cout.tie(0);
        cout << fixed << setprecision(20);
    #ifdef Local
        freopen("../input.in", "r", stdin);
        freopen("../output.out", "w", stdout);
    #endif
        while(cin >> K) run();
        return 0;
    }
    
    

    E - Independence

    题意:
    给出(n)个点(m)条无向边,现在对于任意两个点,至多有一条边直接连接。
    现在要将这个图划分为两部分,使得两部分都为完全图,问最终每部分最小边数之和为多少。

    思路:

    • 划分为两部分之后的答案很好计算,假设两边的点分别有(x,y)个,那么最终答案就为(frac{xcdot (x-1)}{2}+frac{ycdot (y-1)}{2})
    • 现在就考虑如何划分。
    • 我们取原图的补图,那么最终两个集合中不存在任何一条边即符合条件。
    • 进一步地,我们将这个与二分图等价,其实就将问题转化为二分图问题了。
    • 首先判断二分图是否存在,若存在,先有若干个连通块,每个连通块有两种选择,那么直接背包(dp)一下求出最终所有方案数就行了。

    (一开始还以为能够滚动一维QAQ)
    代码如下:

    Code
    #include <bits/stdc++.h>
    #define MP make_pair
    #define fi first
    #define se second
    #define sz(x) (int)(x).size()
    //#define Local
    using namespace std;
    typedef long long ll;
    typedef pair<int, int> pii;
    const int N = 705;
     
    int n, m;
    bool lnk[N][N];
    int cnt[2];
    int col[N];
    bool f;
     
    void dfs(int u, int c) {
        col[u] = c;
        ++cnt[c];
        for(int v = 1; v <= n; v++) {
            if(lnk[u][v]) {
                if(col[v] == -1) dfs(v, 1 - c);
                else if(col[v] == c) {
                    f = false;
                    return;
                }
            }
        }
    }
     
    pii num[N];
    bool dp[N][N];
     
    void run() {
        memset(col, -1, sizeof(col));
        memset(dp, 0, sizeof(dp));
        f = true;
        for(int i = 1; i <= n; i++)
            for(int j = 1; j <= n; j++) {
                if(i != j) lnk[i][j] = 1;
            }
        for(int i = 1; i <= m; i++) {
            int u, v; cin >> u >> v;
            lnk[u][v] = lnk[v][u] = 0;
        }
        int tot = 0;
        for(int i = 1; i <= n; i++) {
            if(col[i] == -1) {
                cnt[0] = cnt[1] = 0;
                dfs(i, 0);
                num[++tot] = MP(cnt[0], cnt[1]);
            }
        }
        if(f == false) {
            cout << -1 << '
    ';
            return;
        }
        dp[0][0] = 1;
        for(int i = 1; i <= tot; i++) {
            for(int j = 0; j <= n; j++) {
                if (j >= num[i].fi) dp[i][j] |= dp[i - 1][j - num[i].fi];
                if (j >= num[i].se) dp[i][j] |= dp[i - 1][j - num[i].se];
            }
        }
        int ans = 1e9;
        for(int i = 0; i <= n; i++) {
            if(dp[tot][i]) {
                ans = min(ans, i * (i - 1) / 2 + (n - i) * (n - i - 1) / 2);
            }
        }
        cout << ans << '
    ';
    }
     
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(0); cout.tie(0);
        cout << fixed << setprecision(20);
    #ifdef Local
        freopen("../input.in", "r", stdin);
        freopen("../output.out", "w", stdout);
    #endif
        while(cin >> n >> m) run();
        return 0;
    }
    
    

    F - Eating Symbols Hard

    鸽了好久,终于来补了= =

    题意:
    给出一个字符串含有">,<,+,-"四种字符,每种字符代表一种操作,字符串长度不超过(10^5)
    先有一个初始全为(0)的无限长的数组,起点为(0)。"+"代表当前位置加一,"-"与之相反;">"代表往右边走一步,"<"代表往左边走一步。
    现问多少区间([l,r]),只执行该区间内的操作,得到的数组能与执行([1,n])的操作得到的想同。

    思路:
    感觉题意说了一大堆,可能我表述有点问题= =
    可以考虑字符串哈希,哈希函数设计为:

    [h(a)=sum a_ix^i ]

    之后有点不好表述了(果真我表述能力有问题),可以参见代码,代码还是比较好懂的。
    处理区间hash值时注意(hs[l]-hs[r+1]=hs[1]*pos[l-1])这个等式,具体含义可以看代码,这里直接相减是计算上前面那一部分的移动的。
    反正很巧妙QAQ

    Code
    #include <bits/stdc++.h>
    #define MP make_pair
    #define fi first
    #define se second
    #define sz(x) (int)(x).size()
    //#define Local
    using namespace std;
    typedef long long ll;
    typedef unsigned long long ull;
    typedef pair<int, int> pii;
    const int N = 250005, P1 = 1e9 + 7, P2 = 1e9 + 9;
    
    ll qpow(ll a, ll b, ll c) {
        ll ans = 1;
        while(b) {
            if(b & 1) ans = ans * a % c;
            a = a * a % c;
            b >>= 1;
        }
        return ans;
    }
    
    char s[N];
    int n;
    
    struct rolling_hash{
        ll a, b;
        rolling_hash() {
            a = b = 0;
        }
        rolling_hash(ll x) {
            a = x % P1;
            b = x % P2;
        }
        rolling_hash(ll x, ll y) {
            a = x % P1;
            b = y % P2;
        }
        rolling_hash operator + (const rolling_hash& A) const {
            return rolling_hash(a + A.a, b + A.b);
        }
        rolling_hash operator - (const rolling_hash& A) const {
            return rolling_hash(a - A.a + P1, b - A.b + P2);
        }
        rolling_hash operator * (const rolling_hash& A) const {
            return rolling_hash(a * A.a, b * A.b);
        }
        ll get() {
            return a * P2 + b;
        }
    }hs[N], pos[N];
    
    rolling_hash X = 1000003;
    rolling_hash invX = rolling_hash(qpow(X.a, P1 - 2, P1), qpow(X.b, P2 - 2, P2));
    
    unordered_map <ll, int> mp;
    
    void run() {
        mp.clear();
        cin >> s + 1;
        pos[0] = 1;
        for(int i = 1; i <= n; i++) {
            pos[i] = pos[i- 1];
            if(s[i] == '>') {
                pos[i] = pos[i - 1] * X;
            } else if(s[i] == '<') {
                pos[i] = pos[i - 1] * invX;
            }
        }
        hs[n + 1] = 0;
        for(int i = n; i >= 1; i--) {
            hs[i] = hs[i + 1];
            if(s[i] == '+') {
                hs[i] = hs[i] + pos[i];
            } else if(s[i] == '-') {
                hs[i] = hs[i] - pos[i];
            }
        }
        ll ans = 0;
        ++mp[hs[n + 1].get()];
        for(int i = n; i >= 1; i--) {
            rolling_hash now = hs[i] - hs[1] * pos[i - 1];
            ans += mp[now.get()];
            ++mp[hs[i].get()];
    //        cout << ans << '
    ';
        }
        cout << ans << '
    ';
    }
    
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(0); cout.tie(0);
        cout << fixed << setprecision(20);
    #ifdef Local
        freopen("../input.in", "r", stdin);
        freopen("../output.out", "w", stdout);
    #endif
        while(cin >> n) run();
        return 0;
    }
    
    
  • 相关阅读:
    window.parent ,window.top,window.self 详解及parent和opener的区别
    jQuery $.extend()用法总结
    JQuery中each()的使用方法说明
    jQuery.isPlainObject()的作用
    change和onchange、click和onclick的区别
    zabbix客户端一键安装脚本(主动模式监控)
    jumpserver在centos 7上的部署
    用阿里云的免费 SSL 证书让网站从 HTTP 换成 HTTPS
    GitLab的安装及使用教程
    一个客户端一键安装环境和服务的shell脚本
  • 原文地址:https://www.cnblogs.com/heyuhhh/p/11594640.html
Copyright © 2011-2022 走看看