Codeforces Round #671 (Div. 2) AE problem solution

Codeforces Round #671 (Div. 2) AE problem solution
// written in rating value 1987/2184
// The AD in this game is real water...

Contest link: https://codeforces.ml/contest

Question A
Water question

The title means that given a number of length n, two people alternately mark a certain digit on this number. The first hand can only mark the odd-digit numbers, and the second hand can only mark the even-digit numbers. When there is only one position left unmarked, if the number is odd, then the first hand wins, if the number is even, then the second hand wins.

Note that in this question, the numbers that can be marked by two people are completely unrelated to each other. Whether the last remaining number is in the odd position or the even position is only determined by the parity of n. If the last remaining number is an odd number, the first player will definitely want to win. Therefore, if any of the odd numbers is odd, he can guarantee his victory as long as he saves this number until the end. .
The same is true when the last remaining is the even-digit number.

#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;

int32_t main()
{
    
    
    IOS;
    int t;
    cin>>t;
    while(t--)
    {
    
    
        int n;
        cin>>n;
        string s;
        cin>>s;
        bool flag;
        if(n&1)//如果总数量是奇数的话,奇数位上的数比偶数位上多1个,最后剩下的那个数一定是奇数位上的数
        {
    
    
            flag=0;
            for(int i=0;i<n;i+=2)//只要奇数位上的数存在任何一个是奇数,先手的人都可以使得它成为最后一个数,使得自己获胜
                if(s[i]%2) flag=1;
        }
        else//对应总数量是偶数的情况,最后剩下的数一定是偶数位上的数
        {
    
    
            flag=1;
            for(int i=1;i<n;i+=2)//只要偶数位上的数存在任何一个是偶数,后手的人都可以使得它成为最后一个数,使得自己获胜
                if(s[i]%2==0) flag=0;
        }
        if(flag) cout<<1<<endl;
        else cout<<2<<endl;
    }
}

Question B
Summary of simple rules

The question means that given x square squares, you are required to construct as many different perfect steps as possible. The definition of an n-step perfect step is that the number of squares in each column from left to right is 1-n, and this step can be divided into n square parts.

In fact, it is easy to think that such a perfect step must be an axisymmetric figure. Drawing a picture can assist in understanding and drawing conclusions.
First of all, only the steps on the first floor are perfect, while the steps on the second floor are not perfect.
The bottom left and top right of the three-story steps can be filled with a perfect step, and the remaining part is exactly a square.
The lower left and upper right of the 7th floor can be filled with 3 perfect steps, and the remaining part is exactly a square.
…It
can be concluded that the recurrence formula for the number of perfect steps from small to large is f(n+1)=f(n) × \times×f(n)+1

The last data of the sample has given the largest x value of 1e18 when the answer is only 30, so the direct violence cycle is enough.

#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;

ll num[70];

int32_t main()
{
    
    
    IOS;
    int t;
    cin>>t;
    while(t--)
    {
    
    
        ll x;
        cin>>x;
        ll ans=0,cas=1;
        while(x>0)
        {
    
    
            x-=(1+cas)*cas/2;
            if(x>=0) ans++;
            cas=cas*2+1;
        }
        cout<<ans<<endl;
    }
}

Question C
Greedy, classified discussion

The title means that there is a virus spreading on the codeforces website, and it will spread among people with equal ratings. In the beginning, only one person was infected, his rating value was x, and he could not participate in the game (cannot change his rating). Now there are n individuals each have an initial rating. You can change their rating every time you participate in the game, but the sum of all the rating changes must be 0. Now ask how many matches are needed to make everyone infected with the virus.

First, we classify the number of people whose initial rating is equal to x, and set the person whose initial rating is equal to x as cas.
If cas=n, it means that everyone is infected at the beginning, and output 0 directly.
If cas<n but cas>0, it means that some people were infected at the beginning and some were not. We can make the rating value of the infected person all become x through one game, and the total change value is 0, then the corresponding variable is directly added to those who were infected at the beginning. . Therefore, 1 is output directly at this time.
If cas=0, it means that no one is infected at the beginning, and the strategy of the previous situation cannot be adopted.
At this point, we count the sum of the ratings of n individuals. If sum can divide n and sum/n=x, then we can change everyone's rating to x by passing one game.
And if sum/n!=x or sum cannot divide n, we must not be able to infect everyone in one match, but we can create one infected person in one match, and then take the above 0<cas< The strategy of n can infect everyone in 2 matches in total.

#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;

int32_t main()
{
    
    
    IOS;
    int t;
    cin>>t;
    while(t--)
    {
    
    
        int n,x;
        cin>>n>>x;
        int sum=0,cas=0;
        for(int i=0;i<n;i++)
        {
    
    
            int temp;
            cin>>temp;
            if(temp!=x) sum+=temp;
            else cas++;
        }
        if(cas==n) cout<<0<<endl;
        else if(cas) cout<<1<<endl;
        else
        {
    
    
            if(sum%n==0&&sum/n==x) cout<<1<<endl;
            else cout<<2<<endl;
        }
    }
}

D1+D2 questions
Greedy, structure

The question means to give you n numbers, and you need to shuffle them. Make as many numbers as possible that are smaller than the adjacent numbers on the left and right of oneself (the numbers of subscript 1 and subscript n are not counted, that is, the numbers at the beginning and the end are not counted), and output the largest satisfaction Digital quantity, and output any satisfying construction method.

Here we adopt a greedy strategy to construct small numbers for odd subscripts (subscripts start from 0), and even subscripts to construct large numbers.
This is because the numbers on the left and right boundaries are not counted, that is, the subscript 0 must not be counted, and we can at most construct a satisfactory number starting from the subscript 1. And if x[1]<x[2], then x[2] must not be a satisfactory number. That is, our optimal must also be separated by a number that is satisfied by a number structure. That is to say, odd-numbered subscripts must construct relatively small numbers, and even-numbered subscripts must construct relatively large numbers.
After sorting the original numbers directly, the subscripts are placed from left to right to odd subscripts from small to large, and then subscripts are placed from left to right to even subscripts. In this way, we ensure that 1. Even number subscripts are the largest ones, and 2. The minimum value in even number subscripts is not less than the maximum value in odd number subscripts. We arrange this way to ensure that 3. The relatively small number in the even-numbered subscript will be adjacent to the relatively small number in the odd-numbered subscript.
According to the above three points, it can be concluded that such greed is the optimal strategy.

The difference between D1 and D2 is that the numbers of D1 are different, so the number of numbers that meet the conditions is (n-1)/2, and the numbers of D2 may be the same, we need to check the specifics again for There are only numbers that satisfy the conditions. The construction method is exactly the same.

#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;

vector<ll>num;
vector<ll>out;
ll n;

int32_t main()
{
    
    
    IOS;
    cin>>n;
    num.resize(n);
    out.resize(n);
    for(auto &x:num) cin>>x;
    sort(num.begin(),num.end());
    ll tar=0;
    for(ll i=1;i<n;i+=2) out[i]=num[tar++];
    for(ll i=0;i<n;i+=2) out[i]=num[tar++];
    ll ans=0;
    for(ll i=1;i<n;i+=2) if(i+1<n&&out[i-1]>out[i]&&out[i+1]>out[i]) ans++;
    cout<<ans<<endl;
    for(ll i=0;i<n;i++)
    {
    
    
        if(i) cout<<' ';
        cout<<out[i];
    }
    cout<<endl;
}

Question E
Number theory, complexity analysis, structure

The question means that given a number n, you are required to arrange all the factors of n except 1 into a ring, and the logarithm of mutual prime between two adjacent positions is required to be the least. Output a construction scheme, and output the least relatively prime logarithm.

It is easy to think of it here that all the factors of n can be obtained by combining different powers of the prime factors of n. Then we noticed that for the two prime factors a and b. If we put a number c between a and b that can divide both a and b, it becomes a, c, b. Then between a and c, you can put all factors that can divide a, and between c and b, you can put all factors that can divide b.
From this we can first find out all the different prime factors of n, and then put a factor that divides the n of the two adjacent prime factors between them, and then all other numbers must be at least these prime factors One of the factors is divisible, that is, it can be inserted into the interval as described in the previous paragraph.

The next thing is to think about whether this scheme is always feasible.
For these prime factors, the product of two prime factors must also be a factor of n, and the products obtained between different prime factors must not be equal, so we can insert their product between adjacent prime factors Construction plan. But this scheme, in n=a × \times× b is not true, because at this time n has only three factors, a, b and n, if according to the above scheme, it will be constructed into a, n, b, n. Repeated n twice. At this time, we can actually only construct a, n, b, so there will be a pair of adjacent coprime numbers. At this time, we can directly output a, n, b, endl, 1, endl. Therefore, we judge that n is exactly equal to a× \times× b.
But this will wa at the tenth point. Because if there are only two prime factors, although we can construct 0 pairs of adjacent prime numbers, we will also use a× \timestwice×b。

At this time, we need to analyze the complexity, because the question here says that the number of factors of all n is not more than 2e5. According to the factors are composed of different powers of prime factors, it is easy to get the number of prime factors. A small value will not exceed 1e3, so we can take a more violent solution.

Exclude n=a × \times× b This is the case where a pair of adjacent prime numbers must be constructed. In other cases, the choice of the number between adjacent prime factors that can divide them can be directly found in all factors of n.

the above.

#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=31630;

vector<ll>prime;//线性筛筛出sqrt(1e9)内的所有素数
bool v[maxn];

void primes()
{
    
    
    for(ll i=2;i<maxn;i++)
    {
    
    
        if(!v[i])
        {
    
    
            v[i]=1;
            prime.push_back(i);
        }
        for(ll j=0;prime[j]<maxn/i;j++)
        {
    
    
            v[prime[j]*i]=1;
            if(i%prime[j]==0) break;
        }
    }
}


int32_t main()
{
    
    
    IOS;
    primes();
    int t;
    cin>>t;
    while(t--)
    {
    
    
        ll n;
        cin>>n;
        vector<ll>primes_now;//保存当前的n分解质因数后有几个不同的质因子
        ll temp=n;
        for(ll i=0;i<prime.size()&&prime[i]<=temp/prime[i];i++)
        {
    
    
            if(temp%prime[i]==0)
            {
    
    
                primes_now.push_back(prime[i]);
                while(temp%prime[i]==0) temp/=prime[i];
            }
        }
        if(temp>1) primes_now.push_back(temp);

        unordered_map<ll,bool>M;//保存n除了1外的因子有哪些,记录它是否被使用过
        for(ll i=2;i<=n/i;i++)
        {
    
    
            if(n%i==0)
            {
    
    
                M[i]=0;
                M[n/i]=0;
            }
        }
        M[n]=0;


        if(primes_now.size()==2&&primes_now[0]*primes_now[1]==n) cout<<primes_now[0]<<' '<<primes_now[1]<<' '<<n<<endl<<1<<endl;
        //如果n刚好能拆分成两个质因子相乘,就是唯一一种特殊的情况,我们无法构造出0对相邻互质而只能构成1对相邻互质的特殊情况,直接输出三个数字和对数1。
        else
        {
    
    
            vector<ll>mid(primes_now.size());//mid[i]当前n分解的质因子,第i个和第i+1个中间插入的数是哪一个
            for(ll i=0;i<primes_now.size();i++)//直接暴力for一遍,质因子数量是很少的
            {
    
    
                for(auto &x:M)//去n的所有因数里面找既能整除第i个质因子又能整除第i+1个质因子的数
                {
    
    
                    if(!x.second&&x.first%primes_now[i]==0&&x.first&&x.first%primes_now[(i+1)%primes_now.size()]==0)
                    {
    
    
                        mid[i]=x.first;
                        x.second=1;
                        break;
                    }
                }
                M[primes_now[i]]=1;
            }

            for(ll i=0;i<primes_now.size();i++)//然后把剩下没使用过的数字继续暴力放到第i个质因子和mid[i]中间,只需要满足整除第i个质因子即可
            {
    
    
                cout<<primes_now[i]<<' ';
                for(auto &x:M)
                {
    
    
                    if(!x.second&&x.first%primes_now[i]==0)
                    {
    
    
                        cout<<x.first<<' ';
                        x.second=1;
                    }
                }
                cout<<mid[i]<<' ';
            }
            cout<<endl<<0<<endl;
        }
    }
}

Guess you like

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