zoukankan      html  css  js  c++  java
  • 2018 Multi-University Training Contest 4

    Problem B. Harvest of Apples

    #include <bits/stdc++.h>
    using namespace std;
    
    const int maxn = 1e5 + 50;
    typedef long long ll;
    const ll mod = 1e9 + 7;
    ll fac[maxn], sing[maxn], inv[maxn];
    void init(int n)
    {
        fac[0] = sing[0] = inv[0] = fac[1] = sing[1] = inv[1] = 1;
        for(int i = 2; i <= n; i++)
        {
            fac[i] = fac[i - 1] * i % mod;
            sing[i] = (mod - mod / i) * sing[mod % i] % mod;
            inv[i] = inv[i - 1] * sing[i] % mod;
        }
    }
    ll C(int n, int m)
    {
        ll res =  fac[n]* inv[m] % mod * inv[n - m] % mod;
       // printf("%d %d %lld
    ",n, m, res);
        return res;
    }
    struct Seg
    {
        int l, r, belong, id;
    }seg[maxn];
    ll ans[maxn];
    bool cmp(Seg A, Seg B)
    {
        if(A.belong == B.belong) return A.r < B.r;
        return A.l < B.l;
    }
    int main()
    {
        init(1e5 + 5);
        int block = sqrt(1e5);
        int T; scanf("%d", &T);
        for(int p = 1; p <= T; p++)
        {
            scanf("%d %d", &seg[p].l, &seg[p].r);
            seg[p].belong = seg[p].l / block;
            seg[p].id = p;
        }
        sort(seg + 1, seg + T + 1, cmp);
        int l = 0, r = 0;
        ll res = 1;
        for(int i = 1; i <= T; i++)
        {
            while(l < seg[i].l)
            {
                res = (res * 2LL % mod + mod - C(l, r)) % mod;
                l++;
            }
            while(l > seg[i].l)
            {
                l--;
                res = (res + C(l, r)) * sing[2] % mod;
            }
            while(r < seg[i].r)
            {
                r++;
                res = (res + C(l, r)) % mod;
            }
            while(r > seg[i].r)
            {
                res = (res + mod - C(l, r)) % mod;
                r--;
            }
            ans[seg[i].id] = res;
           // printf("%lld
    ", ans[seg[i].id]);
        }
        for(int i = 1; i <= T; i++)
        {
            printf("%lld
    ", ans[i]);
        }
        return 0;
    }
    Code

    Problem E. Matrix from Arrays

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int maxn = 1e3 + 50;
    int a[maxn];
    int sum = 0;
    int m[50][50];
    int L;
    ll solve(ll x, ll y)
    {
        x++, y++;
        ll res = 0;
        int cntx = x / (2 * L);
        int cnty = y / (2 * L);
        res += (ll)cntx * cnty * sum; ///加上整块的
        int tempx = x - cntx * 2 * L;
        int tempy = y - cnty * 2 * L;
        ll sum1 = 0 ,sum2 = 0;
        for(int i = 0; i < tempx; i++) ///加上半块半块的
        {
            for(int j = 0; j < 2 * L; j++)
            {
                sum1 += m[i][j];
            }
        }
        for(int i = 0; i < 2 * L; i++)
        {
            for(int j = 0; j < tempy; j++)
            {
                sum2 += m[i][j];
            }
        }
        res += sum1 * cnty;
        res += sum2 * cntx;
        ///加上残块的
        for(int i = 0; i < tempx; i++)
        {
            for(int j = 0; j < tempy; j++)
            {
                res += m[i][j];
            }
        }
        return res;
    }
    
    int main()
    {
        int T; scanf("%d", &T);
        while(T--)
        {
            scanf("%d", &L);
            sum = 0;
            for(int i = 0; i < L; i++) scanf("%d", &a[i]), sum += 4 * L * a[i];
            int cur = 0;
            for(int i = 0; i < 45; i++)
            {
                for(int j = 0; j <= i; j++)
                {
                    m[j][i - j] = a[cur];
                    cur = (cur + 1) % L;
                }
            }
           /* for(int i = 0; i < 10; i++)
            {
                for(int j = 0; j < 10; j++)
                {
                    printf("%3d ", m[i][j]);
                }
                printf("
    ");
            }*/
           // printf("%lld
    ",solve(1, 2));
            int q; scanf("%d", &q);
            while(q--)
            {
                int x1, y1, x2, y2;
                scanf("%d %d %d %d", &x1, &y1, &x2, &y2);
                ll ans = solve(x2, y2) - solve(x2, y1 - 1) - solve(x1 - 1, y2) + solve(x1 - 1, y1 - 1);
               // printf("%lld %lld %lld %lld
    ",solve(x2, y2), solve(x2, y1 - 1), solve(x1 - 1, y2), solve(x1 - 1, y1 - 1));
                printf("%lld
    ", ans);
            }
        }
        return 0;
    }
    Code

    Problem J. Let Sudoku Rotate

    #include <bits/stdc++.h>
    using namespace std;
    
    char s[20][20], w[5][5];
    int vis[50];
    int ans = 100;
    int tmp[5][5];
    void Rota(int a, int b) ///顺时针旋转90度
    {
        for(int i = 0; i < 4; i++)
        {
            for(int j = 0; j < 4; j++)
            {
                tmp[j][3 - i] = s[a + i][b + j];
            }
        }
        for(int i = 0; i < 4; i++)
        {
            for(int j = 0; j < 4; j++)
            {
                s[a + i][b + j] = tmp[i][j];
            }
        }
    }
    int cnt = 0;
    int check(int a, int b)
    {
        ///memset(vis, 0, sizeof(vis)); 从dls那里学了个姿势,不用每次memset了
        for(int i = a; i < a + 4; i++)  ///判断我这个小块的前面有没有重复的
        {
            cnt++;
            for(int j = 0; j < b + 4; j++)
            {
               // printf("%d
    ", s[i][j]);
                if(vis[s[i][j]] == cnt)
                {
                    //printf("%d %d %d
    ", i, j, cnt);
                    return 0;
                }
                vis[s[i][j]] = cnt;
            }
        }
        for(int i = b; i < b + 4; i++)
        {
            cnt++;
            for(int j = 0; j < a + 4; j++)
            {
                if(vis[s[j][i]] == cnt)
                    return 0;
                vis[s[j][i]] = cnt;
            }
        }
        return 1;
    }
    void dfs(int x, int y, int sum)
    {
        if(x == 4)
        {
            ans = min(ans, sum);
            return;
        }
        if(sum >= ans) return;
        if(y == 4) return dfs(x + 1, 0, sum);
        for(int i = 0; i < 4; i++)
        {
            if(check(x * 4, y * 4))
            {
                dfs(x, y + 1, sum + i);
            }
            Rota(x * 4, y * 4);
        }
    }
    int main()
    {
        int T; scanf("%d", &T);
        while(T--)
        {
            for(int i = 0; i < 16; i++) scanf("%s", s[i]);
            for(int i = 0; i < 16; i++)
            {
                for(int j = 0; j < 16; j++)
                {
                    s[i][j] = s[i][j] - '0';
                }
            }
            memset(vis, 0, sizeof(vis));
            ans = 100;
            cnt = 0;
            dfs(0, 0, 0);
            printf("%d
    ", ans);
        }
        return 0;
    }
    Code

    Problem G. Depth-First Search

          终于把思路理清楚了。

          整体思想是逐位的思想。

          首先考虑$b[1]$,我们发现如果$root<b[1]$,那后面怎么排列都满足条件。那我们需要统计这些情况,我们发现每一个点的孩子节点是$deg[i]-1$,只有根节点的孩子节点是$deg[i]$,那我们可以维护一个$res$,令$res=prod_{i=1}^n (deg[i]-1)!$。再计算以$root$为根的排列情况,就$ans += res * deg[root]$就可以了。

          考虑完$root<b[1]$的情况,进一步考虑$root=b[1]$的情况。此时先将$res$更新为$res=res*deg[b[1]]$,代表此时以$b[1]$为根出发。和前一种情况类似,走的下一个节点$<b[2]$,那后面怎么排列都满足条件。查询$root$子树中节点$<b[2]$的个数$t$$($可以用$n$颗树状数组解决$)$,那$ans = ans + frac{res*t}{deg[b[1]]}$,就是我从$t$中任选一个点走下一步,$b[1]$少了能任意选择的情况,此时$res$就要修改为$res=frac{res}{deg[b[1]]}$,$deg[b[1]]--$。然后再去考虑$second($第二个遍历点$)=b[2]$的情况。

          后面的点依次像上面一样遍历。

          慎用$memset!!!$

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int maxn = 1e6 + 50;
    int b[maxn];
    int fac[maxn], sing[maxn], inv[maxn];
    int deg[maxn];
    vector<int> g[maxn];
    const ll mod = 1e9 + 7;
    void init(int n)
    {
        fac[0] = fac[1] = sing[0] = sing[1] = inv[0] = inv[1] = 1;
        for(int i = 2; i <= n; i++)
        {
            fac[i] = (ll)fac[i - 1] * i % mod;
            sing[i] = (ll)(mod - mod / i) * sing[mod % i] % mod;
            inv[i] = (ll)inv[i - 1] * sing[i] % mod;
        }
    }
    struct Tree
    {
        vector<int> T;
        int n;
        void init(int _n)
        {
            n = _n;
            T.resize(n + 1);
            for(int i = 0; i <= n; i++) T[i] = 0;
        }
        void add(int x, int v)
        {
            x++;
           // printf("%d %d
    ", x, v);
            for(int i = x; i <= n; i += (i & -i)) T[i] += v;
        }
        int query(int x)
        {
            x++;
            //printf("%d ", x);
            if(x > n) x = n; ///所有的节点都比我小
            //printf("%d
    ", x);
            int res = 0;
            for(int i = x; i > 0; i -= (i & -i)) res += T[i];
            return res;
        }
    }tr[maxn];
    int pre[maxn];
    void dfs1(int u, int fa)
    {
        sort(g[u].begin(), g[u].end()); ///对子节点排序,方便在子节点中离散化存储
        pre[u] = fa;
        tr[u].init(g[u].size());
        for(int i = 0; i < g[u].size(); i++)
        {
            int v = g[u][i];
            if(v == fa) continue;
            int tmp = lower_bound(g[u].begin(), g[u].end(), v) - g[u].begin();
            //printf("%d ", v);
            tr[u].add(tmp, 1);
            deg[v]--;
            dfs1(v, u);
        }
    }
    ll ans = 0, res = 0;
    int n, cur = 1, flag = 0;
    void dfs2(int u)
    {
        if(cur >= n || flag || (!u)) return;  /// !u 退回到根节点
        if(deg[u]) ///全部子节点已经被排列
        {
            int tmp = lower_bound(g[u].begin(), g[u].end(), b[cur + 1]) - g[u].begin();
            //printf("%d ", b[cur + 1]);
            int cnt = tr[u].query(tmp - 1);
            ans = (ans + res * cnt % mod * sing[deg[u]] % mod) % mod;
            if(pre[b[cur + 1]] != u) ///不用往下继续了,因为给的b序列就不是一个dfs序列
            {
                flag = 1;
                return;
            }
            cur++;
            tmp = lower_bound(g[u].begin(), g[u].end(), b[cur]) - g[u].begin();
            //printf("%d ", b[cur]);
            tr[u].add(tmp, -1);
            res = res * sing[deg[u]] % mod;
            deg[u]--;
            dfs2(b[cur]);
        }
        else dfs2(pre[u]);
    }
    int main()
    {
        init(1e6);
        int T; scanf("%d", &T);
        while(T--)
        {
            scanf("%d", &n);
            for(int i = 1; i <= n; i++) scanf("%d", &b[i]), g[i].clear() ,deg[i] = 0;
            for(int i = 1; i < n; i++)
            {
                int u, v; scanf("%d %d", &u, &v);
                g[u].push_back(v);
                g[v].push_back(u);
                deg[u]++, deg[v]++;
            }
            ans = 0, res = 1;
            for(int i = 1; i <= n; i++)
            {
                res = res * fac[deg[i] - 1] % mod;
            }
            for(int i = 1; i < b[1]; i++)
            {
                ans = (ans + res * deg[i]) % mod;
            }
            cur = 1, flag = 0;
            res = res * deg[b[1]] % mod;
            dfs1(b[1], 0);
            dfs2(b[1]);
            printf("%lld
    ", ans);
        }
        return 0;
    }
    Code
  • 相关阅读:
    设计模式-单列模式
    linux udp c/s
    linux 命令
    java String
    [转]Android进程间通信--消息机制及IPC机制实现
    Android入门:Activity四种启动模式
    CRT 重启Was
    jquery.cookie.js 使用
    div设置contentEditable="true"作为文本编辑器,定位光标解决办法
    居中展示图片
  • 原文地址:https://www.cnblogs.com/littlepear/p/9417334.html
Copyright © 2011-2022 走看看