zoukankan      html  css  js  c++  java
  • vijos训练之——星辰大海中闪烁的趣题

    看到难度普遍7-9就感觉很劲…再加上doc出品,于是果断入坑。由于知识性内容还没有学完,只能慢慢刷了。

    章节 1. 一些简单的练手题

    1.1 捕风捉影

    这sb题居然智障WA了两次….

    由于是回文串只要枚举前半段,然后瞎几把测试素数就好了。
    顺便学习一波miller-rabin的二次探查。

    复杂度O(nSlgn),S为测试次数。

    #include <bits/stdc++.h>
    using namespace std;
    
    long long power(long long a, long long n, long long mod)
    {
        if (n == 0) return 1%mod;
        long long p = power(a, n>>1, mod);
        p = p*p%mod;
        if (n&1) p = p*a%mod;
        return p;
    }
    
    bool miller_rabin(long long n)
    {
        if (n == 2) return 1;
        if (n < 2 || !(n&1)) return 0;
        int k;
        long long u;
        for (k=0, u=n-1; !(u&1); u>>=1, k++);
        for (int i = 1; i < 20; i++) {
            long long x = rand()%(n-2)+2, pre;
            if (x%n == 0) continue;
            x = power(x, u, n);
            pre = x;
            for (int j = 1; j <= k; j++) {
                x = x*x%n;
                if (x == 1 && pre != 1 && pre != n-1) return 0;
                pre = x;
            }
            if (x != 1) return 0;
        }
        return 1;
    }
    
    long long rev(long long a)
    {
        long long t = 0;
        while (a) t = (t+a%10)*10, a /= 10;
        return t/10;
    }
    long long ans[100005];
    int top = 0;
    int main()
    {
        srand(time(0));
        long long n, m;
        cin >> n >> m;
        if (5 >= n && 5 <= m) ans[++top] = 5;
        if (7 >= n && 7 <= m) ans[++top] = 7;
        int len = 1;
        for (long long i = 1; i <= 10000; i++) {
            long long l = i, r = rev(i);
            long long lk = l*power(10, len, LONG_LONG_MAX)+r;
            if (lk >= n && lk <= m && miller_rabin(lk)) ans[++top] = lk;
            for (int j = 0; j < 10; j++) {
                lk = l*power(10, len+1, LONG_LONG_MAX)+j*power(10, len, LONG_LONG_MAX)+r;
                if (lk >= n && lk <= m && miller_rabin(lk)) ans[++top] = lk;
            }
            if (i >= power(10, len, LONG_LONG_MAX)-1) len++;
        }
        sort(ans+1, ans+top+1);
        top = unique(ans+1, ans+top+1)-ans-1;
        for (int i = 1; i <= top; i++) printf("%lld
    ", ans[i]);
        return 0;
    }

    1.2 小白逛公园

    以前写线段树查询从来都是直接返回答案…做了这题才发现可以返回一个完整的节点信息。

    就是线段树维护总和,最大子段和,左起最大子段和,右起最大子段和。

    复杂度O(nlgn)

    #include <bits/stdc++.h>
    using namespace std;
    
    const int MAXN = (1<<19)+2;
    struct node {
        int lsum, rsum, sum, subsum, l, r;
        node():l(0),r(0){}
        friend bool operator == (const node &a, const node &b)
        {
            return a.l == b.l;
        }
    } tree[MAXN*2];
    int a[MAXN], n, m;
    #define nil tree[0]
    
    node link(const node &l, const node &r)
    {
        if (l == nil) return r;
        if (r == nil) return l;
        node nd;
        nd.sum = l.sum + r.sum;
        nd.lsum = max(l.lsum, l.sum+r.lsum);
        nd.rsum = max(r.rsum, r.sum+l.rsum);
        nd.subsum = max(l.subsum, max(r.subsum, l.rsum+r.lsum));
        return nd;
    }
    
    void build(int nd, int l, int r)
    {
        if (l < r) {
            build(nd*2, l, (l+r)/2);
            build(nd*2+1, (l+r)/2+1, r);
            tree[nd] = link(tree[nd*2], tree[nd*2+1]);
            tree[nd].l = l, tree[nd].r = r;
        } else {
            tree[nd].l = tree[nd].r = l;
            tree[nd].sum = tree[nd].lsum = tree[nd].rsum = tree[nd].subsum = a[l];
        }
    }
    
    void dfs(int nd, int tab = 0)
    {
        if (!tree[nd].l) return;
        for (int i = 1; i <= tab; i++) putchar(' ');
        //printf("[%d,%d] : %d,%d,%d,%d
    ", tree[nd].l, tree[nd].r, tree[nd].lsum, tree[nd].rsum, tree[nd].subsum, tree[nd].sum);
        dfs(nd*2, tab+2);
        dfs(nd*2+1, tab+2);
    }
    
    void update(int nd, int pos, int dat)
    {
        if (tree[nd].l == tree[nd].r) {
            tree[nd].sum = tree[nd].lsum = tree[nd].rsum = tree[nd].subsum = dat;
        } else {
            int l = tree[nd].l, r = tree[nd].r;
            update((pos<=(l+r)/2)?nd*2:nd*2+1, pos, dat);
            tree[nd] = link(tree[nd*2], tree[nd*2+1]);
            tree[nd].l = l, tree[nd].r = r;
        }
    }
    
    node query(int nd, int l, int r)
    {
        if (l > r) return nil;
        if (tree[nd].l == l && tree[nd].r == r) return tree[nd];
        node d = link(query(nd*2, l, min(r, tree[nd*2].r)),
                      query(nd*2+1, max(l, tree[nd*2+1].l), r));
        //printf("[%d,%d] %d %d->%d,%d,%d
    ", tree[nd].l, tree[nd].r, l, r, d.subsum, d.lsum,d .rsum);
        return d;
    }
    
    int main()
    {
        scanf("%d%d", &n, &m);
        tree[0].l = 123231131;
        for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
        build(1, 1, n);
        for (int i = 1; i <= m; i++) {
            int opt, opl, opr;
            scanf("%d%d%d", &opt, &opl, &opr);
            if (opt == 1) {
                if (opl > opr) swap(opl, opr);
                printf("%d
    ",query(1, opl, opr).subsum);
            } else if (opt == 2) {
                update(1, opl, opr);
            } else dfs(1);
        }
        return 0;
    }

    1.3 CoVH之柯南开锁

    一开始以为是反转思考了好久,后来才发现只是按下去。

    最小割经典建图:

    1. Srow
    2. colT
    3. rowcol,if there is something at (row,col)

    正确性是显然的,复杂度O()

    貌似用二分图匹配也可以?但我不会匈牙利那一套理论。

    #include <bits/stdc++.h>
    using namespace std;
    
    const int MAXN = 50005, MAXM = 5000005;
    struct node {
        int to, next, f, neg;
    } edge[MAXM];
    int head[MAXN], top = 0;
    void push(int i, int j, int k)
    {
        ++top, edge[top] = (node) {j, head[i], k, top+1}, head[i] = top;
        ++top, edge[top] = (node) {i, head[j], 0, top-1}, head[j] = top;
    }
    
    int vis[MAXN], bfstime = 0;
    int lev[MAXN], S = 50001, T = 50002;
    queue<int> que;
    
    bool bfs()
    {
        vis[S] = ++bfstime, lev[S] = 0, que.push(S);
        while (!que.empty()) {
            int tp = que.front(); que.pop();
            for (int i = head[tp]; i; i = edge[i].next) {
                if (edge[i].f == 0 || vis[edge[i].to] == bfstime) continue;
                vis[edge[i].to] = bfstime, lev[edge[i].to] = lev[tp]+1, que.push(edge[i].to);
            }
        } 
        return vis[T] == bfstime;
    }
    
    int dfs(int nd, int maxf = 233333333)
    {
        if (nd == T || !maxf) return maxf;
        int ans = 0, t;
        for (int i = head[nd]; i; i = edge[i].next) {
            if (edge[i].f == 0 || lev[edge[i].to] != lev[nd] + 1) continue;
            t = dfs(edge[i].to, min(maxf, edge[i].f));
            ans += t, maxf -= t;
            edge[i].f -= t, edge[edge[i].neg].f += t;
        } 
        if (maxf) lev[nd] = -1;
        return ans;
    }
    
    int dinic()
    {
        int ans = 0;
        while (bfs()) ans += dfs(S);
        return ans;
    }
    
    int n, m;
    char str[105];
    int main()
    {
        scanf("%d%d", &n, &m);
        for (int i = 1; i <= n; i++) push(S, i, 1);
        for (int i = 1; i <= m; i++) push(n+i, T, 1);
        for (int i = 1; i <= n; i++) {
            scanf("%s", str+1);
            for (int j = 1; j <= m; j++) 
                if (str[j] == '1')
                    push(i, n+j, 1);
        }
        cout << dinic() << endl;
        return 0;
    }

    章节 2. 轻松点它们很简单

    2.1 cpc的逃离

    变得难起来了…
    构造问题,由于有二叉树计数考虑用卡特兰数。然后瞎几把搞【雾】。
    复杂度O(lgn)。因为卡特兰数是指数增长,其反函数是对数增长。

    #include <bits/stdc++.h>
    using namespace std;
    
    // C : h(n)=h(n-1)*(4*n-2)/(n+1);
    
    long long h[20];
    
    void work(int n, long long k, bool out_side = 1) // n个节点中编号为k的 
    {
        //cerr << endl << n << " " << k << endl;
        if (k*n == 0) return;
        if (!out_side) putchar('(');
        for (int i = 0; i < n; i++) {
            if (h[i]*h[n-i-1] < k) k -= h[i]*h[n-i-1];
            else {
                work(i, (k-1)/h[n-i-1]+1, 0);
                putchar('X');
                work(n-i-1, k%h[n-i-1]?k%h[n-i-1]:h[n-i-1], 0);
                break;
            }
        }
        if (!out_side) putchar(')');
    }
    
    int main()
    {
        h[0] = 1;
        for (int i = 1; i < 20; i++) h[i] = h[i-1]*(4*i-2)/(i+1);//, printf("%lld
    ", h[i]);
        long long x;
        while (scanf("%lld", &x), x != 0) {
            int i = 1;
            for (; x > h[i]; x -= h[i], i++);
            work(i, x);
            puts("");
        }
        return 0;
    }
  • 相关阅读:
    MY_HOME
    跨站请求伪造CSRF防护方法
    python中的函数参数
    python 中的闭包
    append追加元素绑定事件无效的解决办法
    webservice练习(cxf,axis,httpclient)
    hibernate5 mysql写入中文乱码
    今天面试中遇到的几个sql查询问题
    Eclipse运行maven项目是出现-Dmaven.multiModuleProjectDirectory system property is not set. Check $M2_HOME environment variable and mvn script match.这种问题解决办法
    模拟博客园登录java实现
  • 原文地址:https://www.cnblogs.com/ljt12138/p/6684337.html
Copyright © 2011-2022 走看看