• Codeforces Round #663 (Div. 2) 题解


    比赛网址:https://codeforces.com/contest/1391

    A. Suborrays

    网址:https://codeforces.com/contest/1391/problem/A

    A permutation of length (n) is an array consisting of (n) distinct integers from (1) to n in arbitrary order. For example, ([2,3,1,5,4]) is a permutation, but ([1,2,2]) is not a permutation ((2) appears twice in the array) and ([1,3,4]) is also not a permutation ((n=3) but there is (4) in the array).

    For a positive integer (n), we call a permutation (p) of length (n) good if the following condition holds for every pair (i) and (j) ((1≤i≤j≤n))

    • ((p_i OR p_{i+1} OR … OR p_{j−1} OR p_j))(≥){(j−i+1)}, where OR denotes the bitwise OR operation.
      In other words, a permutation (p) is good if for every subarray of (p), the OR of all elements in it is not less than the number of elements in that subarray.

    Given a positive integer (n), output any good permutation of length (n). We can show that for the given constraints such a permutation always exists.

    Input

    Each test contains multiple test cases. The first line contains the number of test cases (t) ((1≤t≤100)). Description of the test cases follows.

    The first and only line of every test case contains a single integer (n) ((1≤n≤100)).

    Output

    For every test, output any good permutation of length (n) on a separate line.

    Example

    input

    3
    1
    3
    7
    

    output

    1
    3 1 2
    4 3 5 2 7 1 6
    

    Note

    For (n=3, [3,1,2]) is a good permutation. Some of the subarrays are listed below.

    • (3 OR 1=3≥2 (i=1,j=2))
    • (3 OR 1 OR 2=3≥3 (i=1,j=3))
    • (1 OR 2=3≥2 (i=2,j=3))
    • (1≥1 (i=2,j=2))

    Similarly, you can verify that ([4,3,5,2,7,1,6]) is also good.


    考虑到一个结论:(a|b≥a),所以随便排。

    C ++ AC代码

    #include<iostream>
    #include<cstdio>
    using namespace std;
    int n;
    int main()
    {
    	int t;
    	scanf("%d", &t);
    	while(t --)
    	{
    		scanf("%d", &n);	
    		for(int i = 1; i <= n; ++ i) printf("%d ", i);
    		puts("");		
    	}
    	return 0;
    }
    

    B. Fix You

    网址:https://codeforces.com/contest/1391/problem/B

    Consider a conveyor belt represented using a grid consisting of (n) rows and (m) columns. The cell in the (i)-th row from the top and the (j)-th column from the left is labelled ((i,j)).

    Every cell, except ((n,m)), has a direction R (Right) or D (Down) assigned to it. If the cell ((i,j)) is assigned direction R, any luggage kept on that will move to the cell ((i,j+1)). Similarly, if the cell ((i,j)) is assigned direction D, any luggage kept on that will move to the cell ((i+1,j)). If at any moment, the luggage moves out of the grid, it is considered to be lost.

    There is a counter at the cell ((n,m)) from where all luggage is picked. A conveyor belt is called functional if and only if any luggage reaches the counter regardless of which cell it is placed in initially. More formally, for every cell ((i,j)), any luggage placed in this cell should eventually end up in the cell ((n,m)).

    This may not hold initially; you are, however, allowed to change the directions of some cells to make the conveyor belt functional. Please determine the minimum amount of cells you have to change.

    Please note that it is always possible to make any conveyor belt functional by changing the directions of some set of cells.

    Input

    Each test contains multiple test cases. The first line contains the number of test cases (t) ((1≤t≤10)). Description of the test cases follows.

    The first line of each test case contains two integers (n,m) ((1≤n≤100, 1≤m≤100)) — the number of rows and columns, respectively.

    The following n lines each contain m characters. The (j)-th character in the (i)-th line, (a_{i,j}) is the initial direction of the cell ((i,j)). Please note that (a_{n,m}= C).

    Output

    For each case, output in a new line the minimum number of cells that you have to change to make the conveyor belt functional.

    Example

    input

    4
    3 3
    RRD
    DDR
    RRC
    1 4
    DDDC
    6 9
    RDDDDDRRR
    RRDDRRDDD
    RRDRDRRDR
    DDDDRDDRR
    DRRDRDDDR
    DDRDRRDDC
    1 1
    C
    

    output

    1
    3
    9
    0
    

    Note

    In the first case, just changing the direction of ((2,3)) to D is enough.

    You can verify that the resulting belt is functional. For example, if we place any luggage at ((2,2)), it first moves to ((3,2)) and then to ((3,3)).

    In the second case, we have no option but to change the first (3) cells from D to R making the grid equal to RRRC.


    这就是图的连通性。

    C ++ AC代码

    #include<iostream>
    #include<cstdio>
    using namespace std;
    const int SIZE = 100 + 5;
    char map[SIZE][SIZE];
    int n, m;
    int main()
    {
    	int t;
    	scanf("%d", &t);
    	while(t --)
    	{
    		scanf("%d %d", &n, &m);
    		for(int i = 0; i < n; ++ i) scanf("%s", map[i]);
    		int cnt = 0;
    		for(int i = 0; i < m; ++ i)
    		{
    			if(map[n - 1][i] == 'D') ++ cnt;
    		}
    		for(int i = 0; i < n; ++ i)
    			if(map[i][m - 1] == 'R') ++ cnt;
    		printf("%d
    ", cnt);
    	}
    	return 0;
    }
    

    C. Cyclic Permutations

    网址:https://codeforces.com/contest/1391/problem/C

    A permutation of length (n) is an array consisting of (n) distinct integers from (1) to (n) in arbitrary order. For example, [2,3,1,5,4] is a permutation, but ([1,2,2]) is not a permutation ((2) appears twice in the array) and ([1,3,4]) is also not a permutation ((n=3) but there is (4) in the array).

    Consider a permutation (p) of length (n), we build a graph of size (n) using it as follows:

    • For every (1≤i≤n), find the largest (j) such that (1≤j<i) and (p_j>p_i), and add an undirected edge between node (i) and node (j)
    • For every (1≤i≤n), find the smallest (j) such that (i<j≤n) and (p_j>p_i), and add an undirected edge between node (i) and node (j)
      In cases where no such (j) exists, we make no edges. Also, note that we make edges between the corresponding indices, not the values at those indices.

    For clarity, consider as an example (n=4), and (p=[3,1,4,2]); here, the edges of the graph are ((1,3),(2,1),(2,3),(4,3)).

    A permutation (p) is cyclic if the graph built using p has at least one simple cycle.

    Given (n), find the number of cyclic permutations of length (n). Since the number may be very large, output it modulo 109+7.

    Please refer to the Notes section for the formal definition of a simple cycle

    Input

    The first and only line contains a single integer (n) ((3≤n≤10^6)).

    Output

    Output a single integer (0≤x<10^9+7), the number of cyclic permutations of length (n) modulo (10^9+7).

    Examples

    input

    4
    

    output

    16
    

    input

    583291
    

    output

    135712853
    

    Note

    There are (16) cyclic permutations for (n=4). ([4,2,1,3]) is one such permutation, having a cycle of length four: (4→3→2→1→4).

    Nodes (v_1, v_2, …, v_k) form a simple cycle if the following conditions hold:

    • (k≥3).
    • (v_i≠v_j) for any pair of indices (i) and (j). ((1≤i<j≤k))
    • (v_i) and (v_{i+1}) share an edge for all (i) ((1≤i<k)), and (v_1) and (v_k) share an edge.

    这道题很考察算法基本功。
    首先,我最开始考虑怎么样能形成环?事实上,该序列是有环的充分必要条件是存在(a_i>a_j<a_k)((i<j<k)),否则不存在。
    正着想,想了半晌考虑给该序列“塞”上一个数,用计数方法发现重复状态没法统计;
    那么,什么情况不存在呢??事实上,只要该序列先单调递增再单调递减,满足单峰状态即可,而单增和单减则是特殊情况。
    会发现满足一个递推式:设(f[i])代码(i)的排列中有多少不满足题意,必有:(f[i]=f[i-1]<<1)。关于该式可以考虑将最大的数放在峰上,都有两种选择。

    C ++ AC代码

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<cmath>
    using namespace std;
    const int mod = 1000000007;
    int n;
    int main()
    {
    	scanf("%d", &n);
    	long long tmp = 1, p = 1;
    	for(int i = 2; i <= n; ++ i) 
    	{
    		tmp = (long long) tmp * i % mod;
    		p = (long long) p * 2ll % mod;
    	}
    	printf("%d
    ", (tmp - p + mod) % mod);
    	return 0;
    }
    

    D. 505

    网址:https://codeforces.com/contest/1391/problem/D

    A binary matrix is called good if every even length square sub-matrix has an odd number of ones.

    Given a binary matrix a consisting of (n) rows and (m) columns, determine the minimum number of cells you need to change to make it good, or report that there is no way to make it good at all.

    All the terms above have their usual meanings — refer to the Notes section for their formal definitions.

    Input

    The first line of input contains two integers (n) and (m) ((1≤n≤m≤10^6) and (n⋅m≤10^6)) — the number of rows and columns in (a), respectively.

    The following (n) lines each contain (m) characters, each of which is one of (0) and (1). If the (j)-th character on the (i)-th line is (1), then (a_{i,j}=1). Similarly, if the (j)-th character on the (i)-th line is (0), then (a_{i,j}=0).

    Output

    Output the minimum number of cells you need to change to make (a) good, or output (−1) if it's not possible at all.

    Examples

    input

    3 3
    101
    001
    110
    

    output

    2
    

    input

    7 15
    000100001010010
    100111010110001
    101101111100100
    010000111111010
    111010010100001
    000011001111101
    111111011010011
    

    output

    -1
    

    Note

    In the first case, changing (a_{1,1}) to (0) and (a_{2,2}) to (1) is enough.

    You can verify that there is no way to make the matrix in the second case good.

    Some definitions —

    • A binary matrix is one in which every element is either (1) or (0).
    • A sub-matrix is described by (4) parameters — (r_1), (r_2), (c_1), and (c_2); here, (1≤r_1≤r_2≤n) and (1≤c_1≤c_2≤m).
    • This sub-matrix contains all elements (a_{i,j}) that satisfy both (r_1≤i≤r_2) and (c_1≤j≤c_2).
    • A sub-matrix is, further, called an even length square if (r_2−r_1=c_2−c_1) and (r_2−r_1+1) is divisible by (2).

    又是一道状压。
    很显然,当(min(n,m)>=4)时,此题无解。
    至于剩余的数据该怎么处理。
    首先,(n)(m)中有一个数很小,因此,我们可以利用这个性质解题。
    通常,状压DP伴随着预处理工作。
    不妨设(n)最小,可以给(n)分类讨论:(n=2)时一种,(n=3)时一种;
    (0-1)变为二进制,对于当前的(mask),预处理满足题意的状态;
    于是就有了转移方程:(dp[i,mask]=dp[i-1,premask]+calc(mask,digit[i])),其中(calc)代表当前状态与开始矩阵的不同位。

    C ++ AC代码

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<cmath>
    using namespace std;
    const int SIZE = 1000000 + 5, INF = 1 << 30;
    bool valid[10][10] = {};
    int n, m, ans = INF, a[5][SIZE], digit[5], dp[SIZE][10];
    int calc(int x)
    {
    	int res = 0;
    	while(x)
    	{
    		if(x & 1) ++ res;
    		x >>= 1;
    	}
    	return res;
    }
    bool judge(int x, int y)
    {
    	if(n == 3)
    	{
    		int x1 = x % 4, y1 = y % 4;
    		int x2 = x >> 1, y2 = y >> 1, cnt1, cnt2;
    		cnt1 = calc(x1) + calc(y1), cnt2 = calc(x2) + calc(y2);
    		if((cnt1 & 1) && (cnt2 & 1)) return true;
    		return false;
    	} else
    	{
    		if((calc(x) + calc(y)) & 1) return true;
    		return false;
    	}
    }
    void pre_work()
    {
    	for(int i = 0; i < 1 << n; ++ i)
    	{
    		for(int j = i; j < 1 << n; ++ j)
    		{
    			valid[i][j] = valid[j][i] = judge(i, j);
    		}
    	}
    	memset(dp, 0x3f, sizeof(dp));
    	for(int i = 1; i <= m; ++ i)
    	{
    		digit[i] = 0;
    		for(int j = 1; j <= n; ++ j)
    		{
    			digit[i] = digit[i] << 1 | a[j][i];
    		}
    	}
    	return;
    }
    int main()
    {
    	scanf("%d %d", &n, &m);
    	if(min(n, m) >= 4)
    	{
    		puts("-1");
    		return 0;
    	}
    	if(min(n, m) < 2) 
    	{
    		puts("0");
    		return 0;
    	}
    	if(n > m)
    	{
    		swap(n, m);
    		for(int j = 1; j <= m; ++ j)
    		{
    			for(int i = 1; i <= n; ++ i)
    			{
    				scanf("%1d", &a[i][j]);
    			}
    		}
    	} 
    	else
    	{
    		for(int i = 1; i <= n; ++ i)
    		{
    			for(int j = 1; j <= m; ++ j)
    			{
    				scanf("%1d", &a[i][j]);
    			}
    		}
    	}
    	pre_work();
    	for(int i = 0; i < 1 << n; ++ i) dp[1][i] = calc(i ^ digit[1]);
    	for(int i = 2; i <= m; ++ i)
    	{
    		for(int j = 0; j < 1 << n; ++ j)
    		{
    			for(int k = 0; k < 1 << n; ++ k)
    			{
    				if(valid[j][k]) dp[i][j] = min(dp[i][j], dp[i - 1][k] + calc(j ^ digit[i]));
    			}
    		}
    	}
    	for(int i = 0; i < 1 << n; ++ i) ans = min(ans, dp[m][i]);
    	printf("%d
    ", ans);
    	return 0;
    }
    

    E. Pairs of Pairs

    网址:https://codeforces.com/contest/1391/problem/E

    You have a simple and connected undirected graph consisting of (n) nodes and (m) edges.

    Consider any way to pair some subset of these (n) nodes such that no node is present in more than one pair.

    This pairing is valid if for every pair of pairs, the induced subgraph containing all (4) nodes, two from each pair, has at most (2) edges (out of the (6) possible edges). More formally, for any two pairs, ((a,b)) and ((c,d)), the induced subgraph with nodes {(a,b,c,d)} should have at most (2) edges.

    Please note that the subgraph induced by a set of nodes contains nodes only from this set and edges which have both of its end points in this set.

    Now, do one of the following:

    Find a simple path consisting of at least (⌈n/2⌉) nodes. Here, a path is called simple if it does not visit any node multiple times.
    Find a valid pairing in which at least (⌈n/2⌉) nodes are paired.
    It can be shown that it is possible to find at least one of the two in every graph satisfying constraints from the statement.

    Input

    Each test contains multiple test cases. The first line contains the number of test cases (t) ((1≤t≤10^5)). Description of the test cases follows.

    The first line of each test case contains (2) integers (n,m) ((2≤n≤5⋅10^5, 1≤m≤10^6)), denoting the number of nodes and edges, respectively.

    The next (m) lines each contain (2) integers (u) and (v) ((1≤u,v≤n, u≠v)), denoting that there is an undirected edge between nodes (u) and (v) in the given graph.

    It is guaranteed that the given graph is connected, and simple — it does not contain multiple edges between the same pair of nodes, nor does it have any self-loops.

    It is guaranteed that the sum of (n) over all test cases does not exceed (5⋅10^5).

    It is guaranteed that the sum of (m) over all test cases does not exceed (10^6).

    Output

    For each test case, the output format is as follows.

    If you have found a pairing, in the first line output "PAIRING" (without quotes).

    Then, output (k) ((⌈n/2⌉≤2⋅k≤n)), the number of pairs in your pairing.
    Then, in each of the next (k) lines, output (2) integers (a) and (b) — denoting that (a) and (b) are paired with each other. Note that the graph does not have to have an edge between (a) and (b)!
    This pairing has to be valid, and every node has to be a part of at most (1) pair.
    Otherwise, in the first line output "PATH" (without quotes).

    Then, output (k) ((⌈n/2⌉≤k≤n)), the number of nodes in your path.
    Then, in the second line, output (k) integers, (v_1,v_2,…,v_k), in the order in which they appear on the path. Formally, (v_i) and (v_{i+1}) should have an edge between them for every (i) ((1≤i<k)).
    This path has to be simple, meaning no node should appear more than once.

    Example

    input

    4
    6 5
    1 4
    2 5
    3 6
    1 5
    3 5
    6 5
    1 4
    2 5
    3 6
    1 5
    3 5
    12 14
    1 2
    2 3
    3 4
    4 1
    1 5
    1 12
    2 6
    2 7
    3 8
    3 9
    4 10
    4 11
    2 4
    1 3
    12 14
    1 2
    2 3
    3 4
    4 1
    1 5
    1 12
    2 6
    2 7
    3 8
    3 9
    4 10
    4 11
    2 4
    1 3
    

    output

    PATH
    4 
    1 5 3 6
    PAIRING
    2
    1 6
    2 4
    PAIRING
    3
    1 8
    2 5
    4 10
    PAIRING
    4
    1 7
    2 9
    3 11
    4 5
    

    Note

    The path outputted in the first case is the following.
    image
    The pairing outputted in the second case is the following.
    image
    Here is an invalid pairing for the same graph — the subgraph {(1,3,4,5)} has (3) edges.
    image

    Here is the pairing outputted in the third case.
    image
    It's valid because —

    • The subgraph {(1,8,2,5)} has edges ((1,2)) and ((1,5)).
    • The subgraph {(1,8,4,10)} has edges ((1,4)) and ((4,10)).
    • The subgraph {(4,10,2,5)} has edges ((2,4)) and ((4,10)).

    Here is the pairing outputted in the fourth case.

    image


    任选一个点,dfs一遍;
    若发现有节点深度大于(n/2),直接输出。

    否则就考虑配对。
    找 每一层相邻两个节点进行配对最终的配对即为答案。
    证明:
    首先,最深结点深度保证了配对数量至少可以满足题意;
    考虑每一层中任意两个节点(a,b),如果连边,则必不在同一层;
    如果任选两对不同深度的配对,不妨设((a,b)(c,d))。则(c)与该配对无法有两条边。

    C ++ TLE代码(有大佬帮忙改改吗???)

    #include<iostream>
    #include<cstring>
    #include<vector>
    #include<cstdio>
    #include<cmath>
    using namespace std;
    const int SIZE = 500000 + 5;
    vector <int> G[SIZE], table[SIZE];
    bool vis[SIZE];
    int n, m, pair_num = 0, dep[SIZE], fa[SIZE], ans[SIZE][2];
    bool dfs(int u)
    {
    	pair_num -= table[dep[u]].size() >> 1;
    	table[dep[u]].push_back(u);
    	pair_num += table[dep[u]].size() >> 1;
    	if(dep[u] >= (n + 1) >> 1)
    	{
    		puts("PATH");
    		printf("%d
    ", dep[u]);
    		printf("%d ", u);
    		while(u != 1)
    		{
    			u = fa[u];
    			printf("%d ", u);
    		}
    		return true;
    	}
    	for(int i = 0; i < G[u].size(); ++ i)
    	{
    		int v = G[u][i];
    		if(vis[v]) continue;
    		vis[v] = true;
    		fa[v] = u;
    		dep[v] = dep[u] + 1;
    		if(dfs(v)) return true;
    	}
    	return false;
    }
    int main()
    {
    	int t;
    	scanf("%d", &t);
    	while(t --)
    	{
    		scanf("%d %d", &n, &m);
    		for(int i = 1; i <= n; ++ i) G[i].clear(), table[i].clear();
    		int u, v;
    		for(int i = 0; i < m; ++ i)
    		{
    			scanf("%d %d", &u, &v);
    			G[u].push_back(v), G[v].push_back(u);
    		}
    		memset(vis, false, sizeof(vis));
    		vis[1] = true;
    		dep[1] = 1;
    		pair_num = 0;
    		if(dfs(1)) puts("");
    		else
    		{
    			puts("PAIRING");
    			printf("%d
    ", pair_num);
    			for(int i = 1; i <= n / 2; ++ i)
    			{
    				for(int j = 0; j < table[i].size() >> 1; ++ j)
    				{
    					printf("%d %d
    ", table[i][j << 1], table[i][j << 1 | 1]);
    				}
    			}
    		}
    	}
    	return 0;
    }
    

    总结

    感觉C、D、E出的很有区分度,让我学到不少东西。

    参考文献

  • 相关阅读:
    js中的 || 与 && 运算符详解
    区块链技术与应用:02BTC密码学原理
    C# Windows 截图上遇到过的坑
    WPF 实现弹出层
    设计个窗口定位器
    【域渗透】CVE2022–26923
    拿下某学校内网多媒体管控系统
    Pthon操作MongoDB
    MongoDB使用
    python封装MongoDB的使用
  • 原文地址:https://www.cnblogs.com/zach20040914/p/13616445.html
Copyright © 2020-2023  润新知