ZAFU_2021_1_24_2021 Winter Vacation Individual Competition First Game Solution

The solution of the problem is not necessarily unique, here is the solution that I used when I personally solved the problem.

Question A
link to the original question: https://codeforces.com/problemset/problem/1370/A
related tag: rule summary

We have to choose two different numbers to make their greatest common divisor as large as possible.
Suppose we have found that the first number is x, then if the second number is an integer multiple of x, their greatest common divisor is x.
But the question has already said that two different numbers must be selected, so we choose x and 2x, and the greatest common divisor is x.

2x must be less than or equal to n, so the maximum value of x is n/2

#include<bits/stdc++.h>
#define ll long long
#define INF 0x7f7f7f7f //2139062143
#define llINF 9223372036854775807
#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--)
    {
    
    
        int n;cin>>n;
        cout<<n/2<<endl;
    }
}

Question B
link to the original question: https://codeforces.com/problemset/problem/1027/A
related tag: summary of laws

Each character must be changed once.
The two characters with symmetrical positions must only be the same originally, or the ASCII code differs by 2, one +1 and one -1 become the same.
For once to judge whether they are all satisfied.

#include<bits/stdc++.h>
#define ll long long
#define INF 0x7f7f7f7f //2139062143
#define llINF 9223372036854775807
#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--)
    {
    
    
        int n;cin>>n;
        string s;cin>>s;
        bool f=1;
        for(int i=0;i*2<n;i++)
            if(s[i]!=s[n-i-1]&&abs(s[i]-s[n-i-1])!=2) {
    
    f=0;break;}
        if(f) cout<<"YES"<<endl;
        else cout<<"NO"<<endl;
    }
}

Question C
Original question link: https://codeforces.com/problemset/problem/1027/B
Related tags: Summary of laws

We classify the points whose horizontal and vertical coordinates add up to an even number as the first type of points, and classify the points whose horizontal and vertical coordinates add up to an odd number to the second type.
We can first calculate that there are a total of base points of the first type,
and then according to the row label and column label, find the current point from top to bottom from left to right. If it is the second type of point, add base.

Next is how to calculate the current position from top to bottom, from left to right.
Note that there are a=(n+1)/2 points of the first type in the first row, then the number of points of the second type in the first row is b=na points.
And the second row will become b first-type points, a second-type points, and the
third row will become a first-type points, b second-type points
...

We want to calculate the number of points from top to bottom and left to right in the xth row and yth column.
The xth row and the yth column are the (y+1)/2th point in this row.
For the previous x-1 rows, (x-1)/2 pairs of odd and even rows can form a group, each group has a+b points.
When (x-1) is an odd number, add a few points in the x-1th line, plus a or b as appropriate.

The above three add up to the answer (add a base for the second type of points).

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

int main()
{
    
    
    IOS
    ll n,q;
    cin>>n>>q;
    ll base=n*n/2+(n%2?1:0);//第一类点共有多少个
    ll a=(n+1)/2,b=n-a;//a代表第一行的第一类点有多少个,b代表第一行的第二类点有多少个
    while(q--)
    {
    
    
        ll x,y;cin>>x>>y;
        ll temp=x+y,out=(y+1)/2+(x-1)/2*(a+b);
        //out为输出的答案,前面的(x-1)/2是两行两行的对数,每对有a+b个点,而(y+1)/2是第x行的点的个数
        if(temp%2)//如果是第二类点
        {
    
    
            out+=base;//值需要加上第一类点的个数
            if(x%2==0) out+=b;//如果x是偶数,前面的x-1行还剩下一行的第二类点未计算,加上对应个数b
        }
        else if(x%2==0) out+=a;//第一类点;如果x是偶数,前面的x-1行还剩下第x-1行的第一类点未计算,加上对应个数a
        cout<<out<<endl;
    }
}

Question D
Link to the original question: https://codeforces.com/problemset/problem/1285/B
Related tags: Summary of laws

Assuming that there is an interval [l, r], the sum of these values ​​is not less than the total of n numbers.
Then for the left interval [1,l-1] and [r+1,n], the sum x and y of the two intervals satisfies x+y<=0.
In fact, when one of x and y is less than or equal to 0, the other side is taken to the end, then the other cumulative sum is 0, and there must be an interval that meets the conditions.

So directly from left to right and right to left for two times to calculate the sum, if there is a value less than or equal to 0, it is NO.

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

int num[100000+7];

int main()
{
    
    
    IOS
    int t;cin>>t;
    while(t--)
    {
    
    
        int n;cin>>n;
        for(int i=0;i<n;i++) cin>>num[i];
        bool flag=1;
        ll sum=0;
        for(int i=0;i+1<n;i++)
        {
    
    
            sum+=num[i];
            if(sum<=0) flag=0;
        }
        sum=0;
        for(int i=n-1;i>0;i--)
        {
    
    
            sum+=num[i];
            if(sum<=0) flag=0;
        }
        if(flag) cout<<"YES"<<endl;
        else cout<<"NO"<<endl;
    }
}

Question E
Original question link: https://codeforces.com/problemset/problem/1027/C
Related tags: mathematics, conclusion

If we want to construct a rectangle, we must choose two sets of wooden sticks of the same length.
The lengths of the two sticks are a and b respectively.
Circumference T=a+b, and area S=a × \times× b
notice T× \times× T/S is equal to 2+(a/b+b/a).
We want to minimize a/b+b/a. Note that this is a tick function. When the ratio of a and b is the closest, it is the smallest.

So we sort all the sticks first, and then find which ones have the same length, and compare the ones with the closest length.

#include<bits/stdc++.h>
#define ll long long
#define INF 0x7f7f7f7f //2139062143
#define llINF 9223372036854775807
#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--)
    {
    
    
        int n;cin>>n;
        vector<int>num(n);
        for(int i=0;i<n;i++) cin>>num[i];
        sort(num.begin(),num.end());
        vector<int>data;//有哪些长度相等的一对木棒
        for(int i=0;i+1<n;i++)
        {
    
    
            if(num[i]==num[i+1])//第i根和第i+1根凑成一对
            {
    
    
                data.push_back(num[i]);
                i++;
            }
        }
        int tar=0;
        for(int i=1;i+1<data.size();i++)
        {
    
    
            if(data[tar+1]*data[i]>data[tar]*data[i+1]) tar=i;//转换成乘法,避免了乘法运算,找到data[i]/data[i+1]最小的位置
        }
        cout<<data[tar]<<' '<<data[tar]<<' '<<data[tar+1]<<' '<<data[tar+1]<<endl;
    }
}

F question
original question link: https://codeforces.com/problemset/problem/817/C
related tag: two points

For an integer x, we record the sum of its decimal digits as temp.
Note that every time the value of x is +1, due to the carry in decimal, the value of temp may be +1 or decrease.
That is to say, the difference between x and temp, as x increases, it can only become larger, not smaller.

If the condition of dichotomy is satisfied, find the maximum value that is not satisfied with dichotomy, and subtract it from n to get the number of satisfaction.

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

ll change(ll x)
{
    
    
    ll ret=0;
    while(x)
    {
    
    
        ret+=x%10;
        x/=10;
    }
    return ret;
}

int main()
{
    
    
    IOS
    ll n,s;cin>>n>>s;
    ll l=0,r=n;
    while(l<r)
    {
    
    
        ll mid=(l+r)/2+1;
        if(mid-change(mid)>=s) r=mid-1;
        else l=mid;
    }
    cout<<n-l<<endl;
}

Guess you like

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