• 2021航电多校 第一场


    来源

    F- Xor sum (字典树)

    我明白了,以后遇到异或就想字典树!
    先求异或前缀和,然后从左到右遍历区间右端点,用字典树维护答案,求字典树中与当前右端点最近的、异或和大于k的那个位置!
    假设当前右端点为i,i之前的值都插入了字典树,字典树每个结点存储最大的下标。在查询时,访问logk个结点就能得到答案,这是由于每一步都至多只有一个选择,共logk层。

    详见代码实现

    #include <bits/stdc++.h>
    
    #define endl '
    '
    #define IOS std::ios::sync_with_stdio(0); cin.tie(0); cout.tie(0)
    #define mp make_pair
    #define seteps(N) fixed << setprecision(N) 
    typedef long long ll;
    
    using namespace std;
    /*-----------------------------------------------------------------*/
    
    ll gcd(ll a, ll b) {return b ? gcd(b, a % b) : a;}
    #define INF 0x3f3f3f3f
    
    const int N = 1e7 + 10;
    const double eps = 1e-5;
    
    int tr[N][2];
    int pos[N];
    int si;
    void init() {
        tr[0][0] = tr[0][1] = 0;
        for(int i = 0; i <= si; i++) {
            pos[i] = 0;
        }
        si = 0;
    }
    
    int arr[N];
    int n, k;
    int mx;
    void insert(int x, int p) {
        int cur = 0;
        for(int i = mx; i >= 0; i--) {
            bool d =(x & (1 << i));
            if(!tr[cur][d]) {
                tr[cur][d] = ++si;
                cur = si;
                pos[cur] = p;
                tr[cur][0] = tr[cur][1] = 0;
            } else {
                cur = tr[cur][d];
                pos[cur] = p;
            }
        }
    }
    
    int get(int x) {
        int cur = 0;
        int mxp = -1;
        int i;
        for(i = mx; i >= 0; i--) {
            bool d1 = (x & (1 << i)), d2 = (k & (1 << i));
            int nt;
            if(d1 == 0 && d2 == 0) {    
                nt = tr[cur][1];
                if(nt) mxp = max(mxp, pos[nt]);
                cur = tr[cur][0];
                if(!cur) break;
            } else if(d1 == 1 && d2 == 0) {
                nt = tr[cur][0];
                if(nt) mxp = max(mxp, pos[nt]);
                cur = tr[cur][1];
                if(!cur) break;
            } else if(d1 == 0 && d2 == 1) {
                cur = tr[cur][1];
                if(!cur) break;
            } else {
                cur = tr[cur][0];
                if(!cur) break;
            }
        }
        if(i < 0) mxp = max(mxp, pos[cur]); 
        return mxp;
    }
    
    int main() {
        IOS;
        int t;
        cin >> t;
        while(t--) {
            init();
            cin >> n >> k;
            int mxv = 0;
            for(int i = 1; i <= n; i++) {
                cin >> arr[i];
                arr[i] = arr[i - 1] ^ arr[i];
                mxv = max(mxv, arr[i]);
            }
            mx = 0;
            do {
                mx++;
                mxv >>= 1;
            } while(mxv);
            insert(0, 0);
            int len = INF;
            int l, r;
            for(int i = 1; i <= n; i++) {
                int res = get(arr[i]);
                if(res >= 0) {
                    if(i - res < len) {
                        len = i - res;
                        l = res + 1, r = i;
                    } 
                }
                insert(arr[i], i);
            }
            if(len < INF)
                cout << l << " " << r << endl;
            else
                cout << "-1" << endl;
        }
    }
    

    G - Pass!(递推式求通项(特征根方法),离散对数)

    由题容易得到dp方程(dp[0]=0, dp[1]=n-1)

    [dp[i]=(n-2)dp[i-1]+(n-1)dp[i-2] ]

    使用线性代数的知识可以用特征根法求出通项公式,具体步骤如下。


    最终可得通向公式为

    [f(t)=frac{{(-1)}^{t-1}cdot(n-1)+(n-1)^{t+1}}{n} ]

    分奇偶讨论,化为形如(a^xequiv b)的形式,就可以用BSGS解决了,复杂度为(O(sqrt(P)))
    注意要用unordered_map,不要有太多重复计算,不然会T。

    #include <bits/stdc++.h>
    
    #define endl '
    '
    #define IOS std::ios::sync_with_stdio(0); cin.tie(0); cout.tie(0)
    #define mp make_pair
    #define seteps(N) fixed << setprecision(N) 
    typedef long long ll;
    
    using namespace std;
    /*-----------------------------------------------------------------*/
    
    ll gcd(ll a, ll b) {return b ? gcd(b, a % b) : a;}
    #define INF 0x3f3f3f3f
    
    const int N = 1e5 + 10;
    const int M = 998244353;
    const double eps = 1e-5;
    unordered_map<int, int> vals;
    int si;
    vector<int> Bval[N];
    
    inline ll qpow(ll a, ll b, ll m) {
        ll res = 1;
        while(b) {
            if(b & 1) res = (res * a) % m;
            a = (a * a) % m;
            b = b >> 1;
        }
        return res;
    }
    
    ll dp[N];
    int mx = 0;
    
    int solve(int a, int b, bool odd) {
        ll ra = qpow(a, M - 2, M);
        ll val = b * qpow(a, mx, M) % M;
        int res = INF;
        for(int B = mx; B >= 0; B--) {
            if(vals.count(val)) {
                auto& tar = Bval[vals[val]];
                for(auto &A : tar) {
                    if(((A * mx - B) & 1) == odd && A * mx - B < res) {
                        res = A * mx - B;
                        break;
                    }
                }
            }
            val = val * ra % M;
        }
        return res;
    }
    
    int main() {
        IOS;
        // freopen("in.txt","r",stdin);
        int t;
        cin >> t;
        while(1ll * mx * mx < M) mx++;
        while(t--) {
            int n, x;
            cin >> n >> x;
            if(x == 0) cout << 1 << endl;
            else if(x == 1) cout << 0 << endl;
            else if(x == n - 1) cout << 2 << endl;
            else {
                vals.clear();
                for(int i = 1; i <= si; i++) Bval[i].clear();
                si = 0;
    
                ll val = 1;
                ll mxp = qpow(n - 1, mx, M);
                for(int i = 0; i <= mx; i++) {
                    if(vals.count(val))
                        Bval[vals[val]].push_back(i);
                    else {
                        Bval[++si].push_back(i);
                        vals[val] = si;
                    }   
                    val = val * mxp % M;
                }
    
                int ans1 = solve(n - 1, (1ll * n * x - n + 1) % M, 0);
                int ans2 = solve(n - 1, (1ll * n * x + n - 1) % M, 1);
                int res = min(ans1, ans2);
                if(res == INF) cout << -1 << endl;
                else cout << res << endl;
            }
        }
    }
    

    I - KD-Graph

    Update:二分方法很可能会T,之前能过实在是运气太好
    正解是先对边按边权从小到大排序,然后每个阶段用并查集合并边权相同的边,只要某个阶段结束后连通块数为k,答案就是对应的边权;否则无解。

    #include <bits/stdc++.h>
    #define IOS std::ios::sync_with_stdio(0); cin.tie(0); cout.tie(0)
    #define INF 0x3f3f3f3f 
    #define str first
    #define blu second
    using namespace std;
    const int M = 1e6 + 10;
    const int N = 1e5 + 10;
    typedef long long ll;
    typedef pair<int, int> PII;
    
    struct edge {
        int u, v, w;
    };
    bool cmp(const edge& a, const edge &b) {
        return a.w < b.w;
    }
    
    edge ed[M];
    int fa[N];
    int find(int x) {
        if(fa[x] == x) return x;
        return fa[x] = find(fa[x]);
    }
    
    void init(int n) {
        for(int i = 1; i <= n; i++) {
            fa[i] = i;
        }
    }
    
    int main() {
        IOS;
        int t;
        cin >> t;
        while(t--) {
            int n, m, k;
            cin >> n >> m >> k;
            init(n);
            for(int i = 1; i <= m; i++) {
                int u, v, w;
                cin >> u >> v >> w;
                ed[i] = edge{u, v, w};
            }
            sort(ed + 1, ed + 1 + m, cmp);
            int cnt = n;
            if(n == k) {
                cout << 0 << endl;
                continue;
            }
            int D;
            for(int i = 1; i <= m; i++) {
                int u = ed[i].u, v = ed[i].v;
                int fu = find(u), fv = find(v);
                if(fu != fv) {
                    cnt--;
                    fa[fu] = fv;
                }
                if(i + 1 > m || ed[i].w != ed[i + 1].w) {
                    if(cnt <= k) {
                        D = ed[i].w;
                        break;
                    }
                }
            }
            if(cnt == k) cout << D << endl;
            else cout << -1 << endl;
        }    
    }
    /*
    
    */
    

    二分D,将权重大于D的边删除,然后求连通块数量。连通块即满足条件的分组。D越大,分组数越少,满足单调性,可以二分。

    #include <bits/stdc++.h>
    #define IOS std::ios::sync_with_stdio(0); cin.tie(0); cout.tie(0)
    #define INF 0x3f3f3f3f 
    #define str first
    #define blu second
    using namespace std;
    #define endl '
    '
    const int N = 1e6 + 10;
    typedef long long ll;
    typedef pair<int, int> PII;
    vector<PII> np[N];
    int tag = 0;
    int vis[N];
    int D;
    
    void dfs(int p) {
        vis[p] = tag;
        for(auto nt : np[p]) {
            if(vis[nt.first] != tag && nt.second <= D) {
                dfs(nt.first);
            } 
        }
    }
    
    int main() {
        IOS;
        int t;
        cin >> t;
        while(t--) {
            int n, m, k;
            cin >> n >> m >> k;
            for(int i = 1; i <= n; i++) np[i].clear();
            int l = 0, r = 0;
            for(int i = 1; i <= m; i++) {
                int u, v, w;
                cin >> u >> v >> w;
                np[u].push_back({v, w});
                np[v].push_back({u, w});
                r = max(w + 1, r);
            }
            while(l <= r) {
                D = (l + r) / 2;
                tag++;
                int cnt = 0;
                for(int i = 1; i <= n; i++) {
                    if(vis[i] != tag) {
                        cnt++;
                        dfs(i);             
                    }
                }
                if(cnt <= k) {
                    r = D - 1;
                } else {
                    l = D + 1;
                }
            }
            D = l;
            tag++;
            int cnt = 0;
            for(int i = 1; i <= n; i++) {
                if(vis[i] != tag) {
                    cnt++;
                    dfs(i);                    
                }
            }
            if(cnt == k) cout << D << endl;
            else cout << -1 << endl;
        }    
    }
    
  • 相关阅读:
    [转]说说JSON和JSONP,也许你会豁然开朗,含jQuery用例
    [转]Vue-Devtools安装配置教程(献给伸手党)
    [转]vscode 插件推荐
    [转]eclipse中explorer显示方式
    [转]小D课堂
    [转]eclipse中 properties文件编码问题
    [转]windows环境下启动与停止.jar文件
    [转]Maven 国内源配置(2019/2/14)
    [转]Maven 全局配置文件settings.xml详解
    [转]IntelliJ IDEA 2019 上手
  • 原文地址:https://www.cnblogs.com/limil/p/15042182.html
Copyright © 2020-2023  润新知