• 牛客练习赛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:关键点,青蛙过河的队形是一段连续的区间,考虑最左边的青蛙先跳,然后递推就行了。做题总抓不住关键点 ~

  • 相关阅读:
    ArcEngine连接表join
    坐标系统与投影变换及在ARCGIS中的应用
    ArcEngine 最短路径分析(源码)【转载】
    TOC图例符号转换到ListView
    Dijkstra 最短路径算法的一种高效率实现
    添加、删除连接(Join)和关联(Relate)VBA实例
    C# 实现在线软件自动升级程序
    MapX八个技巧
    希腊字母的读法
    经纬度点与投影坐标系下坐标点的互相转换
  • 原文地址:https://www.cnblogs.com/zgglj-com/p/9532275.html
Copyright © 2020-2023  润新知