zoukankan      html  css  js  c++  java
  • 牛客练习赛25

    A 因数个数和

    ps:模板题

    LL ac(int n)
    
    {
    
        LL ans=0;
    
        for(int i=1,temp;i<=n;i=temp+1)
    
        {
    
            temp=n/(n/i);
    
            ans+=(n/i)*(temp-i+1);
    
        }
    
        return ans;
    
    }
    View Code

    最长区间

    题解:线段树维护区间左端点,右端点,中间部分的最长递增子区间的长度。

    inline void upd(int &x, int y) { x < y && (x = y); }
    
    const int N = 100005;
    
    int n, m, tot;
    int L[4 * N], R[4 * N], sum[4 * N], b[N];
    
    void Pushup(int l, int r, int root) {
        int mid = (l + r) >> 1;
    
        L[root] = L[lson];
        if (L[lson] == mid - l + 1 && b[mid] < b[mid + 1]) L[root] += L[rson];
    
        R[root] = R[rson];
        if (R[rson] == r - mid && b[mid] < b[mid + 1]) R[root] += R[lson];
    
        sum[root] = max(sum[lson], sum[rson]);
        if (b[mid] < b[mid + 1]) upd(sum[root], L[rson] + R[lson]);
    
        //cout << root << " " << L[root] << " " << R[root] << " " << sum[root] << endl;
    }
    
    void Build(int l, int r, int root) {
        if (l == r) {
            int x; sc(x);
            b[++tot] = x;
            L[root] = R[root] = sum[root] = 1;
            return;
        }
        int mid = (l + r) >> 1;
        Build(l, mid, lson);
        Build(mid + 1, r, rson);
        Pushup(l, r, root);
    }
    
    void Update(int l, int r, int root, int pos, int x) {
        if (l == r) {
            b[pos] = x;
            return;
        }
        int mid = (l + r) >> 1;
        if (pos <= mid) Update(l, mid, lson, pos, x);
        else Update(mid + 1, r, rson, pos, x);
        Pushup(l, r, root);
    }
    
    
    
    int main()
    {
        sc(n), sc(m);
        Build(1, n, 1);
        int res = max(sum[1], max(L[1], R[1]));
        pr(res);
    
        res = 0;
        while(m--) {
            int pos, x;
            sc(pos), sc(x);
            Update(1, n, 1, pos, x);
            res = max(sum[1], max(L[1], R[1]));
            pr(res);
        }
    
        return 0;
    }
    View Code

    再编号

    ps:找规律,每一项出现的次数是能递推的。

    const int N = 100005;
    const LL mod = 1000000007;
    
    int n, m;
    LL a[N], s[N];
    
    void Inite() {
        a[1] = 0;
        rep(i, 2, N) {
            if (i & 1) a[i] = ((n - 1) * a[i - 1] % mod - n + 1 + mod) % mod;
            else a[i] = ((n - 1) * a[i - 1] % mod + n - 1) % mod;
        }
    }
    
    int main()
    {
        cin >> n >> m;
    
        Inite();
    
        LL sum = 0;
        Rep(i, 1, n) cin >> s[i], sum += s[i];
    
        sum %= mod;
        while(m--) {
            int x, t;
            sc(x), sc(t);
            if (!t) {
                printf("%lld
    ", s[x]);
            }
            else {
                LL ans;
                if (t & 1) {
                    ans = ((a[t] + 1) * sum % mod - s[x] + mod) % mod;
                }
                else {
                    ans = ((a[t] - 1) * sum % mod + s[x]) % mod;
                }
                printf("%lld
    ", ans);
            }
        }
        return 0;
    }
    View Code

     D a-贝利福斯数

    ps:ax + 1 = (ay + 1)(az + 1),x = ayz + y + z,{ x,y,z∈(1,2,3,······,d)},看见这种式子想到了线性筛法,然而实现不了,orz。

    暴力枚举,加一个小优化:i 一定是没被标记过数。

    void Inite(int m) {
        for (LL i = 1; i <= m; ++i) if (!prime[i]) {
            res.pb(i);
            for (LL j = i; a * i * j + i + j <= m; j++) prime[a * i * j + i + j] = 1;
        }
    }
    const int N = 20000007;
    
    int a, n;
    bool vis[N], prime[N];
    
    vector<int> res;
    
    void Inite(int m) {
        Rep(i, 1, m) if (!prime[i]) {
            res.pb(i);
            for (LL j = 1ll * a * i * i + 2 * i; j <= m; j += a * i + 1) prime[j] = 1;
        }
    }
    
    void Solve() {
        int d = (n - 1) / a;
        Inite(d);
    
        rep(i, 0, Size(res)) rep(j, i, Size(res)) {
            LL tp = 1ll * a * res[i] * res[j] + res[i] + res[j];
            if (tp > d) break;
            vis[tp] = 1;
        }
        int cnt = 0;
        Rep(i, 1, d) if (vis[i]) cnt++;
        cout << cnt << endl;
    }
    
    int main()
    {
        cin >> a >> n;
        Solve();
        return 0;
    }
    View Code

     E. 定向

    题解:将无向图看作是有向图,又因为是无向图,所以添加的双向边在tarjan过程中只能用一条边且只经过一次(代码中的vis[ ]),然后跑一遍普通的tarjan算法就行了。如果只有一个强连通分量,且这个图是联通的,则存在方案。否则就impossible。

    inline void upd(int &x, int y) { x < y && (x = y); }
    
    const int N = 1000005;
    
    int n, m, cnt, tot, block;
    int DFN[N], LOW[N], pa[N], head[N], ans[N];
    
    bool use[N], vis[N];
    
    stack<int> S;
    
    struct node { int to, next, id, dd; } e[2 * N];
    
    void Inite() {
        block = tot = cnt = 0;
        mem(head, -1), mem(use, 0);
    }
    
    void addedge(int u, int v, int id, int dd) {
        e[tot].to = v, e[tot].id = id, e[tot].dd = dd, e[tot].next = head[u], head[u] = tot++;
    }
    
    void Tarjan(int u, int p) {
        pa[u] = p;
        DFN[u] = LOW[u] = ++cnt;
        use[u] = 1;
        S.push(u);
        for (int i = head[u]; ~i; i = e[i].next) if (e[i].to != p && !vis[e[i].dd]) {
            vis[e[i].dd] = 1;
            int v = e[i].to;
            ans[e[i].dd] = e[i].id;
            if (!DFN[v]) {
                Tarjan(v, u);
                LOW[u] = min(LOW[u], LOW[v]);
            }
            else if (use[v]) {
                LOW[u] = min(LOW[u], DFN[v]);
            }
        }
        if (DFN[u] == LOW[u]) {
            block++;
            while(S.top() != u) {
                use[S.top()] = 0;
                S.pop();
            }
            use[u] = 0;
            S.pop();
        }
    }
    
    void Solve() {
        Tarjan(1, 0);
    
        bool flag = 0;
        Rep(i, 1, n) if (!DFN[i]) {
            flag = 1;
            break;
        }
    
        if (flag || block != 1) {
            puts("impossible");
        }
        else {
            Rep(i, 1, m) printf("%d", ans[i]);
        }
    }
    
    int main()
    {
        Inite();
    
        sc(n), sc(m);
        Rep(i, 1, m) {
            int u, v;
            sc(u), sc(v);
            addedge(u, v, 1, i);
            addedge(v, u, 0, i);
        }
    
        Solve();
        return 0;
    }
    View Code

     F. 青蛙

    ps:关键点,青蛙过河的队形是一段连续的区间,考虑最左边的青蛙先跳,然后递推就行了。做题总抓不住关键点 ~

  • 相关阅读:
    Nginx负载均衡+代理+ssl+压力测试
    Nginx配置文件详解
    HDU ACM 1690 Bus System (SPFA)
    HDU ACM 1224 Free DIY Tour (SPFA)
    HDU ACM 1869 六度分离(Floyd)
    HDU ACM 2066 一个人的旅行
    HDU ACM 3790 最短路径问题
    HDU ACM 1879 继续畅通工程
    HDU ACM 1856 More is better(并查集)
    HDU ACM 1325 / POJ 1308 Is It A Tree?
  • 原文地址:https://www.cnblogs.com/zgglj-com/p/9532275.html
Copyright © 2011-2022 走看看