Codeforces round #148 (Div. 1)

Source: Internet
Author: User


A


Wool sequence indicates that a continuous subinterval can be found in a sequence so that the interval is different or the value is 0.

The number of sequences is not included in this case.

The range of data in the question is 0 ~ 2 ^ m-1 select n numbers as a sequence

N and m are both 10 ^ 5


Think carefully. The first has m-1, the second is because it cannot be the same as it has 2 ^ m-2, the third is because it cannot be the same as the second, and it cannot be the same as the first two, there are 2 ^ M-3 and so on, get the formula (m-1) * (2 ^ m-2 )*... * (2 ^ m-N)
int mod = 1000000009;int main(){    int n, m;    scanf("%d%d", &n, &m);    if(m < 20 && (1 << m) <= n ) {        printf("0\n");        return 0;    }    long long ans = 1;    for(int i = 0; i < m; i++) {        ans = ans * 2LL % mod;    }    long long res = 1;    for(int i = 1; i <= n; i++) {        long long tmp = ans - i;        if(tmp < 0) tmp += mod;        res = res * tmp % mod;    }    printf("%I64d\n", res);    return 0;}



B

Returns a sequence a and a numerical value H.

Divides the sequence into two parts. A part can be empty.

Then f function compute

If two numbers are in the same part

The value of the f function is the sum of two numbers.

If it is not in the same part, the sum of two numbers plus H

Evaluate a division to minimize the difference between the maximum and minimum values of the f function


There is a greedy solution,

That is, the maximum value of F must be related to the largest number of values in the sequence.

The minimum value must be related to the smallest number of values in the sequence.

Here I get the minimum five and the maximum five

Put the first or second part of enumeration directly.


Why?

Think about it.

It can be found that none of the other situations has been optimized in this case.


int n, h;struct node {    int x, id;}p[111111], tmp[15];int ans[111111];bool cmp(node x, node y) {    return x.x < y.x;}vector<node>lft, rht;int main(){    scanf("%d%d", &n, &h);    for(int i = 0; i < n; i++) {        scanf("%d", &p[i].x);        p[i].id = i;    }    sort(p, p + n, cmp);     int cnt = 0;    if(n > 10) {        for(int i = 0; i < 5; i++) tmp[cnt++] = p[i];        for(int i = n - 5; i < n; i++) tmp[cnt++] = p[i];    } else {        cnt = n;        for(int i = 0; i < n; i++) tmp[i] = p[i];    }    int vs[12];    int d = INF;    int num = 0;    for(int i = 0; i < (1 << cnt); i++) {        lft.clear();        rht.clear();        for(int j = 0; j < cnt; j++) {            node x = tmp[j];            if((1 << j) & i) {                lft.push_back(x);            } else rht.push_back(x);        }        int mx = 0;        int mi = INF;        int sz1 = lft.size();        for(int j = 0; j < sz1; j++) {            for(int k = j + 1; k < sz1; k++) {                mx = max(mx, lft[j].x + lft[k].x);                mi = min(mi, lft[j].x + lft[k].x);            }        }        int sz2 = rht.size();        for(int j = 0; j < sz2; j++) {            for(int k = j + 1; k < sz2; k++) {                mx = max(mx, rht[j].x + rht[k].x);                mi = min(mi, rht[j].x + rht[k].x);            }        }        for(int j = 0; j < sz1; j++) {            for(int k = 0; k < sz2; k++) {                mx = max(mx, lft[j].x + rht[k].x + h);                mi = min(mi, lft[j].x + rht[k].x + h);            }        }        if(d > mx - mi) {            d = mx - mi;            num = 0;            for(int j = 0; j < sz1; j++) vs[num++] = lft[j].id;        }    }    printf("%d\n", d);    for(int i = 0; i < n; i++) ans[i] = 2;    for(int i = 0; i < num; i++) ans[vs[i]] = 1;    for(int i = 0; i < n; i++) printf("%d ", ans[i]);    printf("\n");    return 0;}


C

A rootless tree

Directed edge

Start from no more than two vertices on the tree and traverse all vertices,

Ask how many directed edges need to be changed

So it's a tree DP.

The enumerated root is the first vertex,

Then the second point requires DP.

To traverse all vertices from the root, you need to modify the edge direction and calculate the number of edges that each vertex needs to modify to access all its subtree.

Then open DP [N] [2] in the array.

DP [u] [0] indicates the number of edges to be modified from u to the root.

DP [u] [1] indicates the number of edges to be modified from the heel to the u


struct node {    int v, w;    node() {}    node(int _v, int _w) {v = _v; w = _w;}};vector<node> g[3333];int ss[3333], dp[3333][2];int total;void dfs0(int u, int f, int x) {    total += x;    ss[u] = ss[f] + x;    int sz = g[u].size();    for(int i = 0; i < sz; i++) {        int v = g[u][i].v;        int w = g[u][i].w;        if(v == f) continue;        dfs0(v, u, w);    }}void dfs(int u, int f, int x) {    if(f == 0) {        dp[u][0] = dp[u][1] = 0;    } else {        dp[u][1] = dp[f][1] + x;        dp[u][0] = min(dp[f][0], dp[f][1]) + !x;    }    int sz = g[u].size();    for(int i = 0; i < sz; i++) {        int v = g[u][i].v;        int w = g[u][i].w;        if(v == f) continue;        dfs(v, u, w);    }}int n;int main(){    int u, v;    scanf("%d", &n);    for(int i = 1; i <= n; i++) g[i].clear();    for(int i = 1; i < n; i++) {        scanf("%d%d", &u, &v);        g[u].push_back(node(v, 0));        g[v].push_back(node(u, 1));    }    int ans = INF;    for(int i = 1; i <= n; i++) {        ss[i] = 0;        total = 0;        dfs0(i, 0, 0);        dfs(i, 0, 0);        for(int j = 1; j <= n; j++) ans = min(ans, total - ss[j] + min(dp[j][0], dp[j][1]));    }    printf("%d\n", ans);    return 0;}



D.

No


E

After reading acmonster, I can understand it. In fact, it is still very vague.


There is a directed graph with the same edge length.

N <= 100

A person must take a bus from the start point to the end point

Then there are several buses with their respective starting and ending points.

Ensure that there is a bus every second, that is, the person can transfer to the corresponding bus at a certain point.

Then these buses are very strange. From their own start point to the end point, they will randomly go through a shortest path.

Ask now, the smallest (he transfers in the worst case)

Is to find a line to minimize the number of times he transfers to the bus in the worst case.


This is because of the number of transfer requests, so this figure cannot follow the Dag's DP Method.

First, pre-process the shortest circuit between any two points.

Then save the bus lines that each point must pass.

Then the DP

From the end point to the start point DP

Very violent

DP [I] [J] indicates the minimum number of transfers when a person is on the node I on the J car

But there are two cases:

One is that this point must be on this bus line.

One is that this point may be on this bus line or not on this bus line.

The first case is the final legal solution.

The second is used to assist the first


Then, during the update, for each vertex, enumerate the bus and check whether the adjacent contacts of the vertex are valid relative to the path, this means that the adjacent point should be closer to the end point of the path,

Even if this point does not appear on the bus route, it should be updated to make the key points behind it updated. In fact, it is equivalent to a virtual one, extend the bus line

For these valid adjacent contacts, select the worst

Then, when enumerating the transfer, it must be this point on this bus line, because the transfer must be at these points to transfer, or the worst case is that the car cannot be reached.

Then, if the optimal value is updated, the entire DP repeat this process.


int dis[111][111], dp[111][111];vector<int>g[111], bus[111];int bx[111], by[111], m, n, t, src, des;bool pass[111][111];int main(){    int u, v;    scanf("%d%d%d%d", &n, &m, &src, &des);    for(int i = 1; i <= n; i++)        for(int j = 1; j <= n; j++)            if(i != j) dis[i][j] = INF;    for(int i = 0; i < m; i++) {        scanf("%d%d", &u, &v);        dis[u][v] = 1;        g[u].push_back(v);    }    for(int k = 1; k <= n; k++) {        for(int i = 1; i <= n; i++) {            for(int j = 1; j <= n; j++)                if(dis[i][j] > dis[i][k] + dis[k][j])                    dis[i][j] = dis[i][k] + dis[k][j];        }    }    m = 0;    scanf("%d", &t);    while(t--) {        scanf("%d%d", &u, &v);        if(dis[u][v] != INF) {            m++;            bx[m] = u;            by[m] = v;        }    }    for(int i = 1; i <= m; i++) {        u = bx[i], v = by[i];        for(int j = 1; j <= n; j++) {            if(dis[u][v] == dis[u][j] + dis[j][v]) pass[i][j] = 1;            for(int k = 1; k <= n; k++) {                if(k != j && dis[u][k] == dis[u][j] && dis[k][v] == dis[j][v]) {                    pass[i][j] = 0;                    break;                }            }            if(pass[i][j]) bus[j].push_back(i);        }    }    for(int i = 1; i <= n; i++) {        for(int j = 1; j <= m; j++) {            if(i == des && pass[j][i]) dp[i][j] = 0;            else dp[i][j] = INF;        }    }    bool flag = 1;    while(flag) {        flag = 0;        for(int i = 1; i <= n; i++) {            for(int j = 1; j <= m; j++) {                int mx = -1;                for(int k = 0; k < g[i].size(); k++) {                    v = g[i][k];                    if(dis[i][by[j]] != dis[v][by[j]] + 1) continue;                    //if(!pass[j][i] || !pass[j][v]) continue;                    mx = max(mx, dp[v][j]);                }                if(mx != -1 && mx < dp[i][j]) {                    dp[i][j] = mx;                    flag = 1;                }                for(int k = 0; k < bus[i].size(); k++) {                    v = bus[i][k];                    if(dp[i][v] + 1 < dp[i][j]) {                        dp[i][j] = dp[i][v] + 1;                        flag = 1;                    }                }            }        }    }    int ans = INF;    for(int i = 1; i <= m; i++)        if(pass[i][src]) ans = min(ans, dp[src][i] + 1);    if(ans == INF) ans = -1;    printf("%d\n", ans);    return 0;}




Codeforces round #148 (Div. 1)

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.