Codeforces Round #663 (Div. 2) AD problem solution

Codeforces Round #663 (Div. 2) AD problem solution
//Written in the large rating value of 2184/2184, small rating value of 1887/1887
//Large star, the small player , ranking 890, rating value + 6
//After cutting ABC in 19 minutes in this field, after analyzing the first-level conclusion of D, I think that the remaining situation is at most 3 × \times× 3 matrix
// enumerate a wave of violence to the situation as white Re
// find themselves are wrong after reconstruction code again return to the right dp ideas, but this time mentality became impatient again
// to The preprocessing of the input data was done very badly, and it was forced to be divided into four cases if...else classification and discussion, resulting in a relatively huge amount of code
// There are four kinds of equations for state transition, and the mentality of long code becomes more irritable after
errors.// The final result is that it took 101 minutes and failed to write this inscription with the correct idea.

//Reflection to sum up, my problem lies in two points
//1. mentality.
//Recent competitions have been written too smoothly, relying on fast hand-scores, and failing to refactor the code of the whole question, my mental quality failed to keep
up.//How to manage and adjust my mentality reasonably when writing the questions is not smooth Need more exercise
// Code style.
//Too much trust in my ability to classify and discuss, and to aggravate my own shortcomings of over-belief in my conclusions when my mentality is irritable
//Unwilling to continue to summarize and optimize the conclusions to optimize data and algorithm operations, resulting in increased code size and difficulty in maintaining. Worsened the mentality

// Every time you make a mistake and failure, you are laying the foundation for a better self tomorrow

Contest link: https://codeforces.com/contest/1391 Question
A
Time to pass: 4min
digit operation mentally retarded question

Misreading the meaning of the question was regarded as an exclusive OR operation, which took some time.
The question means that for an arrangement of length n, for any interval, it is necessary to satisfy that the OR operation result of all numbers in this interval is not less than the length of this interval.

First, the result of the OR operation is not less than the two numbers involved in the operation.
Second, this is an arrangement. You take any interval of length L. This interval must have a number greater than or equal to L.

Nothing... output this arrangement in any order.

#include<bits/stdc++.h>
#define ll long long
#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
using namespace std;

int main()
{
    
    
    IOS;
    int t;
    cin>>t;
    while(t--)
    {
    
    
        ll n;
        cin>>n;
        for(ll i=1;i<=n;i++) cout<<i<<' ';
        cout<<endl;
    }
}

Question B
Time to pass: 5min
observation summary

Given a n × \times× m area, each area has only'D' and'R' representing two directions, downward and right.
Now ask you to modify the direction of at least a few plots, so that starting from any plot in this area, you can reach point (n, m)

First observe the last line. Since we can only go down and to the right and must be able to reach point (n, m), the direction of this line must be R except for point (n, m).
After discussing the other lines above, each The last position (i, m) of a row is also due to the reason that point (n, m) can only be reached down and to the right, and the direction of these positions must all be the
other remaining plots of D. No matter how they are constructed, Since the direction can only go down or right, it will eventually go to the last row or the last column, and after the above structure, the last row and the last column can all go to (n, m), so the remaining area does not need to do anything change.

Calculate the number of plots that are not R except for the point (n, m) in the last row.
Calculate the number of plots that
are not D except for the point (n, m) in the last column. Add the two together.

#include<bits/stdc++.h>
#define ll long long
#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
using namespace std;

string s[107];

int32_t main()
{
    
    
    IOS;
    int t;
    cin>>t;
    while(t--)
    {
    
    
        ll n,m;
        cin>>n>>m;
        for(ll i=0;i<n;i++) cin>>s[i];
        ll ans=0;
        for(ll i=0;i+1<n;i++)
            if(s[i][m-1]!='D') ans++;
        for(ll i=0;i+1<m;i++)
            if(s[n-1][i]!='R') ans++;
        cout<<ans<<endl;
    }
}

Question C
Time to pass: 10min
rule summary, structure

We are required to construct a permutation so that there is a closed loop after building an undirected graph according to the following two rules.
1. For any subscript i that satisfies 1<=i<=n, find the largest subscript j that satisfies 1<=j<i and the value corresponding to subscript j is greater than the value corresponding to subscript i, between i and j Construct an undirected edge between
2. For any subscript i satisfying 1<=i<=n, find the smallest subscript j that satisfies i<j<=n and the value corresponding to subscript j is greater than the value corresponding to subscript i , Construct an undirected edge between i and j.
Note that the edge is established between the subscripts i and j, not between the values ​​corresponding to the subscripts i and j

First of all, we need to think about when a closed loop will be constructed.
From the discussion of three numbers, we can notice:
Permutation: 3 1 2
Permutation: 2 1 3
Subscript: 1 2 3
These two permutations, subscript 2 corresponds to the smallest number 1, and subscript (1, 2 Both) and (2, 3) will create edges.
For subscript 1 and subscript 3, no matter which value the two subscripts correspond to is larger or smaller, (1, 3) will create an edge.
It can be found that a closed loop has been formed at this time.

It can be generalized from this conclusion that if there is a position in our arrangement where the value is both smaller than the left side and smaller than the right side (when the waveform is built according to the value, there is a trough), then there must be a closed loop.

So what are the permutations that do not meet the above conditions, and will these permutations form a closed loop?
There is no arrangement of troughs, which means that there
is only one crest. In other words, for an arrangement of length n, there is a subscript i that satisfies:
1. For the area to the left of the subscript i, from left to right is Monotonically increasing
2. For the area on the right side of the subscript i, it is monotonically decreasing from left to right.
For such a sequence of numbers, it is easy to get, the entire graph has only n-1 items composed of subscript i and other n-1 subscripts The edges form a tree structure and there is no closed loop.

Therefore, we only need to calculate the total number of permutations and subtract the number of permutations without troughs.
The total number of permutations is n! The number of permutations
without troughs. Our construction method can be thought of as swinging to n positions in the order from small to large 1-n. Since we cannot have troughs, we only It can be placed on the far left or right of the current placeable area. There are two options each time (except when the last number n is placed, there is only one position), and the number of options is 2^(n-1)

Take the arrangement n=5 as an example.
At the beginning there are five vacancies:………………
We start to place 1, which can be placed on the far left or on the far right.
We are on the far left: 1…………

Continue to swing 2. It can be placed on the far left or on the far right.
We are on the far right: 1……… 2

Continue to swing 3, it can be placed on the leftmost side to form: 1 3…… 2 can also be placed on the rightmost side to form: 1…… 3 2

Continue to place the last 5 hours, give an example at will: 1 3… 4 2
At this time, our 5 has only one option

Calculate n!-2^(n-1)

#include<bits/stdc++.h>
#define ll long long
#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
using namespace std;
const ll mod=1e9+7;

int32_t main()
{
    
    
    IOS;
    ll n;
    cin>>n;
    ll ans=1,rest=1;//ans计算n!,rest计算2^(n-1)
    for(ll i=2;i<=n;i++)
    {
    
    
        ans=ans*i%mod;
        rest=rest*2%mod;
    }
    cout<<(ans-rest+mod)%mod<<endl;
}

Question D:
Model conversion, dp
//After a white serve was given during the game, I immediately returned to the correct idea, but the preprocessing was too poor. I wrote a monster of nearly 300 lines in the four cases and wrote the subscript of the inverse dp array. The more you modify your mentality after wa, the more it will explode.//Maintaining your
mentality and good preprocessing are both important

First of all, we need to deduce under what circumstances cannot be constructed.
When we exist 4 × \times× 4 sub-matrix, notice that there are four areas that do not overlap each other 2× \times× 2 matrices, the number of 1s in these matrices are all odd numbers, then our current 4× \timesThe number of 1s contained in the sub-matrix of × 4 is these four 2× \timesThe sum of the × 2 matrix must be an even number, which is contrary to the requirement.
From this, when there is 4 × \times× 4 sub-matrix cannot be constructed, directly output -1, which is the case of n>3 and m>3

For the cases that can be constructed, let's preprocess it and transpose the current matrix into a matrix with n<m to facilitate the subsequent unified code. During the game, I just didn't transpose to force it.

It is easy to get, at this time, there are only three cases of 1, 2, and 3.
In other words, we only have two lines of 2 × \times× 2 matrix, we count the number of 1s contained in these matrices, and classify them as 0 and 1 according to whether they need to be changed. The matrix that needs to be changed is 1, and the matrix that does not need to be changed is 0.

For each column, there are at most two matrices, we use binary to represent, the first row is the first bit of the binary, the second row is the second bit of the binary:
0=00 corresponds to the two 2 × \times of this column× 2 matrix does not need to be changed
1=01 corresponds to 2× \timesin the first row of this column× 2 matrix needs to be changed
2=10 corresponds to 2× \timesin the second row of this column× 2 matrix needs to be changed
3=11 2× \timescorresponding to one or two rows of this column× 2 matrix needs to be changed
. The state of each column is stored in the num[] array. Our goal is to calculate the minimum number of operations to change the entire num array to 0

And for n × \times× m area,
changing a certain number will cause the state of the matrix containing it to change from 1 to 0, or from 0 to 1 (corresponding to the exclusive OR operation).
If we change the numbers in the first and last columns, it will only It affects the matrix of the first column or the matrix of the last column,
and changing the number in the middle area will not only affect the 2× \times of thecorresponding column of that number.× 2 matrix will affect the 2× \timesof the previous column× 2 matrix influence

And the impact, we can complete the XOR operation. Take a look at the code dp transfer process.

#include<bits/stdc++.h>
#define ll long long
#define llINF 9223372036854775807
#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
using namespace std;
const ll maxn=1e6+7;

string s[maxn];
ll n,m;
ll num[maxn];//num[i]的二进制代表在第i列对应的2*2矩阵是否需要进行更改,10代表第二层需要改变,01代表第一层需要改变
ll dp[maxn][4];//dp[i][j]代表对于第i列,我们把1到i-1列全部更新为满足条件后,第i列情况为j需要的最少次数

bool field[3][maxn];

int32_t main()
{
    
    
    IOS;
    cin>>n>>m;
    for(ll i=0;i<n;i++)
        cin>>s[i];
    if(n>3&&m>3) cout<<-1<<endl;
    else
    {
    
    
        if(n>m)//预处理,转化成数字方便后续代码,且转置为n<m的矩阵
        {
    
    
            for(ll i=0;i<m;i++)
                for(ll j=0;j<n;j++)
                    field[i][j]=s[j][i]-'0';
            swap(n,m);
        }
        else
        {
    
    
            for(ll i=0;i<n;i++)
                for(ll j=0;j<m;j++)
                    field[i][j]=s[i][j]-'0';
        }
        for(ll i=0;i+1<m;i++)
        {
    
    
            for(ll j=0;j+1<n;j++)
            {
    
    
                ll temp=0;
                if(field[j][i]) temp++;
                if(field[j][i+1]) temp++;
                if(field[j+1][i]) temp++;
                if(field[j+1][i+1]) temp++;
                if(temp%2==0) num[i+1]+=(1<<j);//注意这里下标变为i+1了,从1开始方便后面dp
            }
        }
        ll lim=1<<(n-1);
        dp[0][0]=dp[0][1]=dp[0][2]=dp[0][3]=0;
        for(ll i=1;i<m;i++)
        {
    
    
            for(ll j=0;j<lim;j++)
            {
    
    
                if(j) dp[i][j^num[i]]=dp[i-1][j]+1;//每一列改变时,不仅会改变当前列的2*2矩阵,也会改变前一列的2*2矩阵
                else dp[i][0^num[i]]=dp[i-1][0];//不改变当前列数字的情况,不必+1
            }
        }
        ll ans=llINF;
        for(ll i=1;i<lim;i++) ans=min(ans,dp[m-1][i]+1);//最后一列我们还可以单独进行改变操作
        ans=min(ans,dp[m-1][0]);
        cout<<ans<<endl;
    }
}

Guess you like

Origin blog.csdn.net/StandNotAlone/article/details/107904201