vjudge_XJ_Contest0@8/4/2018

vjudge_XJ_Contest0

A.Spheres

CodeChef - KSPHERES
Chinese

Eugene has a sequence of upper hemispheres and another of lower hemispheres. The first set consists of N upper hemispheres indexed 1 to N and the second has M lower hemispheres indexed 1 to M. The hemispheres in any sequence can have different radii.

He is now set out on building spheres using them. To build a sphere of radius R, he must take one upper half of the radius R and one lower half of the radius R. Also, he can put a sphere into a bigger one and create a sequence of nested concentric spheres. But he can't put two or more spheres directly into another one.

Examples:
vjudge_XJ_Contest0@8/4/2018_第1张图片

vjudge_XJ_Contest0@8/4/2018_第2张图片

If there is a sequence of (D+1) nested spheres, we can call this sequence as a D-sequence.

vjudge_XJ_Contest0@8/4/2018_第3张图片

vjudge_XJ_Contest0@8/4/2018_第4张图片

Eugene has to find out how many different X-sequence are possible (1 <= X <= C). An X sequence is different from another if the index of any of the hemisphere used in one X-sequence is different from the other. Eugene doesn't know how to do it, so Chef agreed to help him. Of course, Chef is too busy now and he asks you to help him.

Input
The first line contains a three integers: N denoting the number of upper sphere halves, M denoting the number of lower sphere halves and C.

The second line contains N space-separated integers U1, U2, ..., UN denoting the radii of upper hemispheres.
The third line contains M space-separated integers L1, L2, ..., LM denoting the radii of lower hemispheres.

Output
Output a single line containing C space-separated integers D1, D2, ..., DC, where Di is the number of ways there are to build i-sequence in modulo 109+7.

Constraints
\(1 ≤ N ≤ 10^5\)
\(1 ≤ M ≤ 10^5\)
\(1 ≤ C ≤ 10^3\)
\(1 ≤ Ui ≤ C\)
\(1 ≤ Li ≤ C\)

Subtasks
Subtask 1: 1 ≤ N, M, C ≤ 10 - 15 points
Subtask 2: 1 ≤ N, M, C ≤ 100 - 25 points
Subtask 3: Original constraints - 60 points

Example
Input:

3 4 3
1 2 3
1 1 3 2

Output:

5 2 0

Explanation
We can build spheres with such radii:
R=1 and there are 2 ways to do it. (We can choose any of 2 lower hemispheres with R=1)
R=2 and there is 1 way to do it.
R=3 and there is 1 way to do it.
We can build these 1-sequences:
1->2 and there are 2 ways to do it. ( sphere with radius 1 is inside sphere with radius 2, we can choose any of 2 ways of building sphere with radius 1)
1->3 and there are 2 ways to do it.
2->3 and there is 1 way to do it.
2 + 2 + 1 = 5
We can build these 2-sequences:
1->2->3 and there are 2 ways to do it.
We can't build 3-sequences, because we don't have 4 spheres of different radii.

Solution
先预处理出每种球的组合方案
在将组合方案数相乘在求和,可以用dp来做

//04/08/18 09:37
#include 
#include 
#define C 1010
#define PSC 1000000007

using namespace std;
typedef long long LL;

LL u[C], l[C], w[C], q[C], f[C][C];

int main() {
    int n, m, c, maxi = 0;
    scanf("%d%d%d", &n, &m, &c);
    for (int i = 1; i <= n; ++i) {
        int x;
        scanf("%d", &x);
        u[x]++;
        maxi = max(maxi, x);
    }
    for (int i = 1; i <= m; ++i) {
        int x;
        scanf("%d", &x);
        l[x]++;
        maxi = max(maxi, x);
    }
    int cnt = 0;
    for (int i = 1; i <= maxi; ++i) {
        w[i] = u[i] * l[i] % PSC;
        if (w[i] > 0) q[++cnt] = w[i];
    }
    for (int i = 1; i <= cnt; ++i)
        f[i][1] = (f[i - 1][1] + q[i]) % PSC;
    for (int i = 1; i <= cnt; ++i)
        for (int j = 2; j <= min(c+1,i); ++j)
            f[i][j] = (f[i - 1][j - 1] * q[i] % PSC + f[i - 1][j]) % PSC;
    for (int i = 2; i <= c; ++i) {
        printf("%lld ", f[cnt][i]);
    }
    printf("%lld\n", f[cnt][c + 1]);
    return 0;
}

B.Sereja and Commands

CodeChef - SEACO
Chinese

Sereja has an array \(A\) consisting of \(n\) integers. Initially, all the elements of array are zero.

Sereja writes down m commands on a piece of a paper. The commands are enumerated from \(1\) to \(m\). These commands can be of the following two types of commands:

\(l r (1 ≤ l ≤ r ≤ n)\) — Increase all elements of the array by one, whose indices belongs to the range \([l, r]\)
\(l r (1 ≤ l ≤ r ≤ m)\) — Execute all the commands whose indices are in the range \([l, r]\). It's guaranteed that \(r\) is strictly less than the enumeration/number of the current command.
Can you please help Sereja in executing all the commands written on this piece of paper.

Input
The first line of the input contains an integer \(T\) denoting the number of test cases. The description of \(T\) test cases follows.

The first line contains integers \(n\) and \(m\). Next m lines contain Sereja's commands in the format, described in statement: \(t, l, r\), where t - number of type (\(1\) or \(2\)).

Output
For each test case on different lines print an array a, after executing all the commands. The numbers have to be separated by spaces. As the numbers can be quite large, print them modulo 109 + 7.

Constraints
\(1 ≤ T ≤ 3\)
\(1 ≤ n, m ≤ 10^5\)

Subtasks
Subtask #1 (20 points): 1 ≤ n, m ≤ 10
Subtask #2 (30 points): 1 ≤ n, m ≤ 1000
Subtask #3 (50 points): original constraints]

Example
Input:

3
5 5
1 1 2
1 4 5
2 1 2
2 1 3
2 3 4
1 2
1 1 1
1 1 1
10 10
1 1 10
2 1 1
2 1 2
2 1 3
2 1 4
2 1 5
2 1 6
2 1 7
2 1 8
2 1 9

Output:

7 7 0 7 7
2
512 512 512 512 512 512 512 512 512 512

Explanation:
Example case 1..
After the first command, the resulting array is [1 1 0 0 0], after second [1 1 0 1 1].
On third command, we repeat the 1'st and the 2'nd command, so that resulting array is [2 2 0 2 2].
After fourth command, the array will looks like [4 4 0 4 4].
Last command will apply 3'rd and 4'th commands, which by themselves will apply 1'st, 2'nd, 1'st, 2'nd, 3'rd(1'st, 2'nd), so resulting arrays is [7 7 0 7 7].

Solution
全部读入后,倒着离线处理,利用差分来维护每个操作被调用的次数
详见代码

#include 
#include 
#define N 100010
#define PSC 1000000007

using namespace std;
typedef long long LL;

LL x[N], l[N], r[N], a[N], f[N];
int main() {
    int t;
    scanf("%d", &t);
    while(t--) {
        int n, m;
        scanf("%d%d", &n, &m);
        for (int i = 1; i <= m; ++i)
            scanf("%d%d%d", &x[i], &l[i], &r[i]);
        LL now = 1;
        memset(a, 0, sizeof(a));//最终答案的差分数组
        memset(f, 0, sizeof(f));//操作次数的差分数组
        for (int i = m; i >= 1; --i) {
            now = (now + f[i]) % PSC;
            if (x[i] == 2) {
                f[r[i]] = (f[r[i]] + now) % PSC;
                f[l[i] - 1] = (f[l[i] - 1] - now) % PSC;
            }
            else {
                a[l[i]] = (a[l[i]] + now) % PSC;
                a[r[i] + 1] = (a[r[i] + 1] - now) % PSC;
            }
        }
        LL ans = 0;
        for (int i = 1; i < n; ++i) {
            ans = (ans + a[i]) % PSC;
            if (ans < 0) ans += PSC;
            printf("%d ", ans);
        }
        ans = (ans + a[n]) % PSC;
        if (ans < 0) ans += PSC;
        printf("%d\n", ans);
    }
    return 0;
}

C.Blocked websites

CodeChef - WSITES01
Chinese

Mike is a network administrator in a university. One of his primary responsibilities in the job is to create an effective firewall so that the students are not able to visit the blocked sites in the network.

The network have access to exactly \(N\) sites. Some of these can be blocked. The names of the sites will be given in lowercase English letters.

The firewall will consist of several filters. A filter is a string that should be a prefix of some blocked site, and it should not be a prefix of any unblocked site. You want to minimize the sum of length of filters in the firewall so that for each of the blocked site, there should be a filter that contains the name of blocked site(filter is a prefix of blocked site).

Input
The first line of the input contains an integer \(N\) denoting the number of sites in the network.

Then \(N\) lines follow, each of them describes the site. Each line starts from the char \(C\). If the site is unblocked, \(C\) is equal to +, otherwise \(С\) is equal to -., followed by a string denoting the name of the site.

Output
If it is not possible to choose set of filters and satisfy all constraints, output a single line containing an integer \(-1\).

Otherwise, in the first line print the number of filters \(K\) in the firewall. Then print \(K\) lines, in each line print the chosen filter. Please dislpay them in lexicographical order. You can prove that answer will be unique.

Constraints
\(1 ≤ N ≤ 2 * 10^5\)
The sum of lengths of names of sites does not exceed \(2*10^5\)
No two sites have same name.

Subtasks
Subtask #1 (30 points) \(1 ≤ N,\) the sum of lengths of names of sites \(≤ 3 * 10^3\)
Subtask #2 (70 points) Original constraints

Example
Input:

4

  • codeforces
  • codechef
  • youtube
  • google

Output:

2
codef
y

Explanation
You can see that the filter codef is a prefix of the blocked site codeforces, but not a prefix of approved sites codechef and google. Similarly, filter y is also a prefix of blocked site youtube, but not a prefix of the approved sites. You can also see that there exists at least one filter for both the blocked sites codeforces and youtube.

(CodeChef & CodeForces的竞争很明显了啊)
维护两棵Trie,一棵保存可以进入的网站,一棵需要block的答案
最后排序输出即可
还有这道题目读入格式有坑!!!
(以后还是多用scanf读东西)

#include 
#define N 200010
#define C 26

using namespace std;

int trie1[N][C], trie2[N][C], tot1, tot2, o;
string p[N], ans[N];

void insert2(string s) {
    int len = s.size(), rt = 0;
    for (int i = 0; i < len; ++i) {
        int id = s[i] - 'a';
        if (!trie2[rt][id]) trie2[rt][id] = ++tot2;
        rt = trie2[rt][id];
    }
}

void traverse(string s, int rt) {
    bool flag = 1;
    for (int i = 0; i < C; ++i) {
        if (!trie2[rt][i]) continue;
        flag = 0;
        traverse(s + (char)(i + 'a'), trie2[rt][i]);
    }
    if (flag) ans[++o] = s;
}

void insert1(string s) {
    int len = s.size(), rt = 0;
    for (int i = 0; i < len; ++i) {
        int id = s[i] - 'a';
        if (!trie1[rt][id]) trie1[rt][id] = ++tot1;
        rt = trie1[rt][id];
    }
}

void search1(string s) {
    int len = s.size(), rt = 0;
    bool flag = 1;
    for (int i = 0; i < len; ++i) {
        int id = s[i] - 'a';
        if (!trie1[rt][id]) {
            insert2(s.substr(0, i + 1));
            flag = 0;
            return;
        }
        rt = trie1[rt][id];
    }
    if (flag) {
        printf("-1\n");
        exit(0);
    }
}

char input[200005];
#include 

int main() {
    int n, cnt = 0;
    scanf("%d", &n);
    for (int i = 1; i <= n; ++i) {
//      getchar();
//      char ch = getchar();
//      assert(ch == '+' || ch == '-');
/*      if (ch == '+') {
            string st;
            cin >> st;
            insert1(st);
        }
        if (ch == '-') cin >> p[++cnt];*/
        scanf("%s", input);
        char ch = input[0];
        scanf("%s", input);
        if (ch == '+') insert1(string(input));
        else p[++cnt] = input;
    }
    
    for (int i = 1; i <= cnt; ++i) {
        search1(p[i]);
    }
    traverse("", 0);
    printf("%d\n", o);
    for (int i = 1; i <= o; ++i)
        cout << ans[i] << endl;
    return 0;
}

D.Cooking Schedule

CodeChef - SCHEDULE
Chinese

Chef is a well-known chef, and everyone wishes to taste his dishes.

As you might know, cooking is not an easy job at all and cooking everyday makes the chef very tired. So, Chef has decided to give himself some days off.

Chef has made a schedule for the next \(N\) days: On \(i\)-th day if \(A_i\) is equal to \(1\) then Chef is going to cook a delicious dish on that day, if \(A_i\) is equal to \(0\) then Chef is going to rest on that day.

After Chef made his schedule he discovered that it's not the best schedule, because there are some big blocks of consecutive days where Chef will cook which means it's still tiring for Chef, and some big blocks of consecutive days where Chef is going to rest which means chef will be bored doing nothing during these days.

Which is why Chef has decided to make changes to this schedule, but since he doesn't want to change it a lot, he will flip the status of at most \(K\) days. So for each day which Chef chooses, he will make it \(1\) if it was \(0\) or he will make it \(0\) if it was \(1\).

Help Chef by writing a program which flips the status of at most \(K\) days so that the size of the maximum consecutive block of days of the same status is minimized.

Input
The first line of the input contains an integer \(T\) denoting the number of test cases.

The first line of each test case contains two integers: \(N\) denoting the number of days and \(K\) denoting maximum number of days to change.

The second line contains a string of length \(N\) , of which the \(i\)-th character is \(0\) if chef is going to rest on that day, or \(1\) if chef is going to work on that day

Output

For each test case, output a single line containing a single integer, which is the minimum possible size of maximum block of consecutive days of the same status achievable.

Constraints
\(1 ≤ T ≤ 11,000\)
\(1 ≤ N ≤ 10^6\)
The sum of \(N\) in all test-cases won't exceed \(10^6\).
\(0 ≤ K ≤ 10^6\)
\(0 ≤ A_i ≤ 1\)

Subtasks
Subtask #1 (20 points): \(N ≤ 10\)
Subtask #2 (80 points): Original Constraints

Example
Input:

2
9 2
110001111
4 1
1001

Output:

2
2

Explanation
Example case 1: The answer is 2 because we can change the string to: 110101011

Example case 2: If we don't change the input string at all, the answer will be 2. It is the best value we can achieve under the given conditions.

Solution
很明显的二分答案
注意处理的时候要特判个数等于1的情况

//04/08/18 11:13
#include 
#include 
#define N 1000010

using namespace std;

int cnt, f[N], p[N], n, k;

inline int make(int x) {
    int ans = 0;
    if (x == 1) {
        for (int i = 1; i <= n; ++i)
            if (p[i] == i % 2) ans++;
        return min(ans, n - ans);
    }
    for (int i = 1; i <= cnt; ++i) {
        ans += f[i] / (x + 1);
    }
    return ans;
}

int main() {
    int t;
    scanf("%d", &t);
    while(t--) {
        scanf("%d%d", &n, &k);
        char ch = getchar();
        int l = 1, r = 0, la = 1;
        cnt = 0;
        for (int i = 1; i <= n; ++i) {
            ch = getchar();
            if (ch == '1') p[i] = 1;
            else p[i] = 0;
            if (p[i] != p[i - 1]) {
                f[++cnt] = i - la;
                r = max(r, f[cnt]);
                la = i;
            }
        }
        f[++cnt] = n + 1 - la;
        r = max(r, f[cnt]);
        while (l < r) {
            int mid = (l + r) >> 1;
            if (make(mid) > k) l = mid + 1;
            else r = mid;
        }
        printf("%d\n", l);
    }
    return 0;
}

E.Flooring

CodeChef - FLOORI4
Chinese

Your task is simple.
You need to find the value of

\[\sum_{i=1}^Ni^4\lfloor{\frac ni}\rfloor\]

As the value could be too large, output it modulo \(M\).

Input
The first contains an integer \(T\), denoting the number of the test cases.

Then there are T lines, each describing a single test case and contains two space separated integers N and M respectively.

Output
For each test case, output the value of summation modulo \(M\) on a separate line.

Constraints
\(1 ≤ M ≤ 100000\)
There are two types of datasets:
\(1 ≤ N ≤ 10^6, 1 ≤ T ≤ 3000\)
\(10^6 ≤ N ≤ 10^{10} , 1 ≤ T ≤ 30\)

Example
Input:

1
4 1000

Output:

373

Explanation
\(1^4*4 + 2^4*2 + 3^4*1 + 4^4*1 = 373\)

不同的\(\lfloor \frac ni\rfloor\)的值最多只有\(\sqrt n\)
每一种的区间是\([i,n/(n/i)]\)
证明只需考虑大于小于\(\sqrt n\)的情况即可
具体的次方和戳这里

//05/08/18 13:57
#include 

using namespace std;
typedef long long LL;

LL n, m;

LL make(LL n) {
    LL MOD = m * 30;//因为m的范围比较小
    LL ans = n % MOD * (n + 1) % MOD * (2 * n % MOD + 1) % MOD * (3 * n % MOD * n % MOD + 3 * n - 1) % MOD;
    return ans / 30;
}

int main () {
    LL t;
    scanf("%lld", &t);
    while(t--) {
        scanf("%lld%lld", &n, &m);
        LL i = 1, la = 0, ret = 0;      
        while (i <= n) {
            LL o = n / i, j = n / o, num = make(j);
            ret = (ret + o % m * ((num - la) % m + m) % m) % m;
            i = j + 1;
            la = num;
        }
        printf("%lld\n", ret);
    }
    return 0;
}

F.Permutation

HDU - 4917

bobo has a permutation \(p_1,p_2,…,p_n\) of \(1,2,…,n\).

Knowing \(m\) extra constraints of form \(p_{a_i}, bobo wanna count the number of different permutations modulo \((10^9+7)\).

It is guaranteed that there is at least one such permutation.

Input
The input consists of several tests. For each tests:
The first line contains \(n,m (1≤n≤40,0≤m≤20)\). Each of the following \(m\) lines contain \(2\) integers \(a_i,b_i(1≤a_i,b_i≤n)\).

Output
For each tests:
A single number denotes the number of permutations.

Sample Input

3 1
1 2
3 2
1 2
2 3

Sample Output

3
1

这几天刚好很认真地补了状压DP和组合数
看到数据范围\(n,m (1≤n≤40,0≤m≤20)\)
直接暴力DP\(O(2^n)\)一定是不行的
但是边数最多只有20条,每个联通块至多有21个点,这种复杂度是可以接受的
同时要预处理出每个点的前驱,最后将组合数与每个块的拓扑序列数全部相乘即可。
另外有大佬告诉我,二维数组寻址特别慢!!!所以不建议使用预分块,在加上二维寻址。

#include 
#include 
#define CHYWZY 1000000007
#define N 45
#define M 22

using namespace std;
typedef long long LL;

LL fa[N], c[N][N], f[N], cnt[N], blk[N], pre[N], dp[1 << M], g[N], a[M], b[M];
bool map[N][N];

LL gfa(LL x) {
    if (fa[x] == x) return x;
    fa[x] = gfa(fa[x]);
    return fa[x];
}

int main() {
    for (LL i = 1; i < N; ++i ) {
        c[i][0] = c[i][i] = 1;
        for (LL j = 1; j < i; ++j) {
            c[i][j] = (c[i - 1][j - 1] + c[i - 1][j]) % CHYWZY;
        }
    }
    LL n, m;
    while (~scanf("%lld%lld", &n, &m)) {
        for (LL i = 1; i <= n; ++i)
            fa[i] = i;
        memset(map, 0, sizeof(map));
        for (LL i = 1; i <= m; ++i) {
            scanf("%lld%lld", &a[i], &b[i]);
            map[a[i]][b[i]] = 1;
            LL f1 = gfa(a[i]), f2 = gfa(b[i]);
            if (f1 < f2) fa[f2] = f1;
            if (f1 > f2) fa[f1] = f2;
        }
        memset(cnt, 0, sizeof(cnt));
        blk[0] = 0;
        for (LL i = 1; i <= n; ++i) {
            LL ff = gfa(i);
            ++cnt[ff];
            if (cnt[ff] == 1) blk[++blk[0]] = ff;
        }
        LL ans = 1, now = 1;
        for (LL i = 1; i <= blk[0]; ++i) {
            ans = ans * c[now + cnt[blk[i]] - 1][cnt[blk[i]]] % CHYWZY;
            LL len = cnt[blk[i]];
            now += len;
            if (len <= 2) continue;
            memset(dp, 0, sizeof(dp));
            memset(pre, 0, sizeof(pre));
            dp[0] = 1;
            LL o = 0;
            for (LL j = 1; j <= n; ++j)
                if (fa[j] == blk[i]) f[++o] = j, g[j] = o;
            for (int j = 1; j <= m; ++j)
                if (fa[a[j]] == blk[i] && fa[b[j]] == blk[i]) pre[b[j]] |= (1 << (g[a[j]] - 1));
            for (LL j = 0; j < (1 << o); ++j)
                for (LL k = 0; k < o; ++k)
                    if (!(j & (1 << k)) && ((j & pre[f[k + 1]]) == pre[f[k + 1]]))
                        dp[j | (1 << k)] = (dp[j | (1 << k)] + dp[j]) % CHYWZY;
            ans = ans * dp[(1 << o) - 1] % CHYWZY;
            
        }
        printf("%lld\n", ans);
    }
    return 0;
}

(总算完整地写完了一篇题解汇总,Fighting!)quq

转载于:https://www.cnblogs.com/Fxkkks/p/9915589.html

你可能感兴趣的:(vjudge_XJ_Contest0@8/4/2018)