zoukankan      html  css  js  c++  java
  • 2019 China Collegiate Programming Contest Qinhuangdao Onsite

    Contest Info


    [Practice Link](https://codeforces.com/gym/102361)
    Solved A B C D E F G H I J K L
    5/12 O - - O - O - - - O Ø -
    • O 在比赛中通过
    • Ø 赛后通过
    • ! 尝试了但是失败了
    • - 没有尝试

    Solutions


    A. Angle Beats

    题意:
    给出(n)个点,每次询问再给出一个点,询问(n)个点中与当前这个点构成直角三角形的方案数。

    D. Decimal

    题意:
    给出一个(n),判断(frac{1}{n})是否是一个无限循环小数。

    思路:
    如果(n)的质因子分解是(2^x5^y)那么不是无限循环

    代码:

    view code
    #include <bits/stdc++.h>
    #define debug(...) { printf("#  "); printf(__VA_ARGS__); puts(""); }
    #define fi first
    #define se second
    #define endl "
    " 
    using namespace std;
    using db = double;
    using ll = long long;
    using ull = unsigned long long; 
    using pII = pair <int, int>;
    using pLL = pair <ll, ll>;
    constexpr int mod = 1e9 + 7;
    template <class T1, class T2> inline void chadd(T1 &x, T2 y) { x += y; while (x >= mod) x -= mod; while (x < 0) x += mod; } 
    template <class T1, class T2> inline void chmax(T1 &x, T2 y) { if (x < y) x = y; }
    template <class T1, class T2> inline void chmin(T1 &x, T2 y) { if (x > y) x = y; }
    inline int rd() { int x; cin >> x; return x; }
    template <class T> inline void rd(T &x) { cin >> x; }
    template <class T> inline void rd(vector <T> &vec) { for (auto &it : vec) cin >> it; }
    inline void pt() { cout << endl; }
    template <class T, class... Ts> void pt(const T& arg, const Ts&... args) { cout << arg << " "; pt(args...); }
    template <class T> inline void pt(const T &s) { cout << s << "
    "; }
    template <class T> inline void pt(const vector <T> &vec) { for (auto &it : vec) cout << it << " "; cout << endl; } 
    ll gcd(ll a, ll b) { return b ? gcd(b, a % b) : a; }
    inline ll qpow(ll base, ll n) { ll res = 1; while (n) { if (n & 1) res = res * base % mod; base = base * base % mod; n >>= 1; } return res; }
    constexpr int N = 1e5 + 10;
    int n; 
    void run() {
    	cin >> n;
    	while (n % 2 == 0) n /= 2;
    	while (n % 5 == 0) n /= 5;
    	if (n == 1) pt("No");
    	else pt("Yes");
    }
    
    int main() {
    	ios::sync_with_stdio(false);
    	cin.tie(nullptr); cout.tie(nullptr);
    	cout << fixed << setprecision(20);
    	int _T; cin >> _T;
    	while (_T--) run();
    	return 0;
    }
    

    F. Forest Program

    题意:
    给出一个无向图,每条边最多存在于一个环中,问多少种移除边的方案使得剩下的每一个连通块都是一棵树

    思路:
    一个环,这个环上至少要切一条边,其他边任意切不切。
    注意刚开始给出的可能不是连通图。

    代码:

    view code
    #include <bits/stdc++.h>
    using namespace std;
    using ll = long long; 
    const int N = 5e5 + 10;
    const ll mod = 998244353;
    int n, m, bit[N];
    vector <vector<int>> G;
    int dep[N], tot, vis[N], Insta[N]; ll res;
    void dfs(int u, int pre) {
    	vis[u] = 1;
    	Insta[u] = 1;
    	for (auto &v : G[u]) if (v != pre) {   
    		if (Insta[v]) { 
    			tot -= dep[u] - dep[v] + 1; 
    			res = 1ll * res * (bit[dep[u] - dep[v] + 1] - 1) % mod;
    			res %= mod;
    		}
    		if (!vis[v]) {
    			dep[v] = dep[u] + 1;
    			dfs(v, u);
    		}
    	}
    	Insta[u] = 0;
    }
     
    int main() {
    	bit[0] = 1;
    	for (int i = 1; i < N; ++i) bit[i] = 1ll * bit[i - 1] * 2 % mod;
    	while (scanf("%d%d", &n, &m) != EOF) {
    		G.clear(); G.resize(n + 1);
    		for (int i = 1; i <= n; ++i) dep[i] = vis[i] = Insta[i] = 0;
    		for (int i = 1, u, v; i <= m; ++i) {
    			scanf("%d%d", &u, &v);
    			G[u].push_back(v);
    			G[v].push_back(u);
    		}
    		tot = m; res = 1; 
    		for (int i = 1; i <= n; ++i) if (!vis[i]) dfs(i, i);
    		res = 1ll * res * bit[tot] % mod;
    		res = (res + mod) % mod;
    		printf("%lld
    ", res);
    	}
    	return 0;
    }
    

    I. Invoker

    题意:
    每种技能需要三种属性,三个属性被按下就可以触发,而顺序不重要。
    但是每次只能保留三个属性,按下第四个的时候第一个会被移除。
    现在给出一个需要使用的技能表,询问怎样按键使得按顺序出发这些技能并且按下的次数最少。

    思路:
    考虑每种技能最多只有六种排列状态,那么(f[i][S])表示前(i)个技能,当前排列状态为(S)的最少按键数。

    代码:

    view code
    #include <bits/stdc++.h>
    using namespace std;
    
    const int N = 1e5 + 10;
    char s[N]; int n;
    map <string, int> f[2];
    map <char, string> mp;
    
    int main() {
        mp['Y'] = "QQQ";
        mp['V'] = "QQW";
        mp['G'] = "EQQ";
        mp['C'] = "WWW";
        mp['X'] = "QWW";
        mp['Z'] = "EWW";
        mp['T'] = "EEE";
        mp['F'] = "EEQ";
        mp['D'] = "EEW";
        mp['B'] = "EQW";
        while (scanf("%s", s + 1) != EOF) {
            f[0].clear(), f[1].clear();
            int n = strlen(s + 1);
            for (int i = 1; i <= n; ++i) {
                int p = i & 1;
                if (i > 1 && s[i] == s[i - 1]) {
                    f[p] = f[p ^ 1];
                    continue;
                }
                f[p].clear();
                string s1 = mp[s[i]];
            //    cout << s1 << endl;
                do {
                    if (i == 1) {
                        f[p][s1] = 3;
                        continue;
                    }
                    f[p][s1] = 1e9; 
                    for (auto &it : f[p ^ 1]) {
                        string s2 = it.first;
                    //    cout << s1 << " " << s2 << endl;
                        int w = it.second;
                        if (s2[1] == s1[0] && s2[2] == s1[1]) {
                            f[p][s1] = min(f[p][s1], w + 1);
                        } else if (s2[2] == s1[0]) {
                            f[p][s1] = min(f[p][s1], w + 2);
                        } else {
                            f[p][s1] = min(f[p][s1], w + 3);
                        }
                    }
                }while (next_permutation(s1.begin(), s1.end()));
            }
            int res = 1e9;
            for (auto &it : f[n & 1]) {
            //    cout << it.first << " " << it.second << endl;
                res = min(res, it.second);
            }
            printf("%d
    ", res + n);
        }
        return 0;
    }
    

    J. MUV LUV EXTRA

    题意:
    给出一个小数,询问小数部分后缀中的(a cdot p - b cdot l)的最大值。
    (a, b)是参数,(p)表示循环节长度,(l)表示后缀长度

    思路:
    将字符串翻转,用(kmp)找循环节即可。

    代码:

    view code
    #include <bits/stdc++.h>
    using namespace std;
    
    typedef long long ll;
    const int N = 1e7 + 10;
    ll a, b;
    char s[N], t[N]; int n;
    void get() {
        int i;
        for (i = 1; s[i]; ++i) {
            if (s[i] == '.') break;
        }
        n = 0;
        for (++i; s[i]; ++i) {
            t[n++] = s[i];
        }
        t[n] = 0;
    }
    struct KMP {
        int Next[N];
        //下标从0开始
        void get_Next(char *s) {
            int len = strlen(s);  
            int i, j;
            j = Next[0] = -1;
            i = 0;
            while (i < len) {
                while (-1 != j && s[i] != s[j]) j = Next[j];
                Next[++i] = ++j;
            }
        }
    }kmp;
    
    int main() {
        while (scanf("%lld%lld", &a, &b) != EOF) {
            scanf("%s", s + 1);
            get();
            reverse(t, t + n); t[n] = 0;
            kmp.get_Next(t);
            ll res = a - b; 
            for (int i = 1; i < n; ++i) {
                ll p = i + 1;
            //    cout << i << " " << kmp.Next[i + 1] << endl;
                ll l = p - kmp.Next[i + 1];
                res = max(res, a * p - b * l);
            }    
            printf("%lld
    ", res);
        }
        return 0;
    }
    
  • 相关阅读:
    字符串hash+回文树——hdu6599
    数位dp——牛客多校H
    线段树区间离散化——牛客多校E
    最小表示法——牛客多校第七场A
    后缀自动机求多串LCS——spojlcs2
    后缀自动机求LCS——spoj-LCS
    后缀自动机求字典序第k小的串——p3975
    后缀自动机模板——不同子串个数p2408
    同构图+思维构造——牛客多校第六场E
    封装,调用函数,以及参数化
  • 原文地址:https://www.cnblogs.com/Dup4/p/11718018.html
Copyright © 2011-2022 走看看