Ozon Tech Challenge 2020 (Div.1 + Div.2, Rated, T-shirts + prizes!)

地址:http://codeforces.com/contest/1305

  

    题意A题写这么长,实际上意思很简单,给出两组长度相等的数,让你给出排列顺序,保证每一列上下加起来不同。

    解析:很水了,小+大=大+小,根据这个,只要上下均按从小到大的顺序排列就可以了。

#include<cstdio>
#include<cstring>
#include<iostream>
#include<queue>
#include<algorithm>
using namespace std;
typedef long long ll;
int a[1005],b[1005];
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        int n;
        cin>>n;
        for(int i=0;i<n;i++)
            cin>>a[i];
        for(int i=0;i<n;i++)
            cin>>b[i];
        sort(a,a+n);sort(b,b+n);
        for(int i=0;i<n-1;i++)
            cout<<a[i]<<" ";
            cout<<a[n-1]<<endl;
        for(int i=0;i<n-1;i++)
            cout<<b[i]<<" ";
            cout<<b[n-1]<<endl;
    }
}

    题意:题意我是理解了有一会儿,特别是这个Output最后关于k的说明,烟雾弹一样搞得人迷糊。给出一个只含(,)的字符串,让你删除最少的字符来使它变成一个标准的(题中的simple string):左边一半全是(,右边一半全是)。输出目标字符串,即删除后得到的,但是下标还是原字符串的。

    解析:经过分析,删除是任意删的,完全没限制,所以说这个k要么是0,要么是1。先特判一下 ( 和 ) 的数目,==0肯定不行,直接输出0。数据很小,直接暴力:从左边开始,i处找到一个(,再从尾开始,j>i处找一个还没用过的)跟它配对,用vis标记用没用过。即每次配一个()。完毕以后,没被vis标过的,即需要删除的地方,当然不需要输出它,输出被vis标记过的。

      第一发WA了,经过检查发现,对于一个已经完美的string,直接输出全坐标就可以,出错的原因是代码写着写着忘了题意,嘿嘿。

#include<cstdio>
#include<cstring>
#include<iostream>
#include<queue>
#include<algorithm>
using namespace std;
typedef long long ll;
const int maxn=1e3+10;
char s[maxn];
int vis[maxn];
int main()
{
    cin>>s;
    int l1=0,l2=0;
    int len=strlen(s);
    for(int i=0;i<len;i++)
    {
        if(s[i]==')')
            l2++;
        else
            l1++;
    }
    if(l2==0||l1==0)
    {
        cout<<"0"<<endl;return 0;
    }
    
    
        for(int i=0;i<len;i++)
        {
            if(s[i]=='('&&!vis[i])
            {
                int ok=0;
                for(int j=len-1;j>i;j--)
                {
                    if(s[j]==')'&&!vis[j])
                    {
                        vis[j]=1;
                        ok=1;
                        break;
                    }
                }
                if(ok)
                    vis[i]=1;
            }
        }
        int k=0,cnt=0;
        for(int i=0;i<len;i++)
        {
            if(vis[i])
            {
                k=1;cnt++;
            }
        }
        if(!k)
            cout<<"0"<<endl;
        else
        {
            cout<<"1"<<endl;
            cout<<cnt<<endl;
            int cnt2=0;
            for(int i=0;i<len;i++)
            {
                if(vis[i]&&cnt2<cnt)
                {
                    cnt2++;
                    cout<<i+1<<" ";
                }
                else if(vis[i]&&cnt2==cnt)
                    {
                        cout<<i+1<<endl;
                    }
            }
        }
}

    题意:就上图中那么乘的,不解释了。

    解析:看数据,暴力肯定不可行。我开始以为是数论,放弃了。赛后一看解析,才是恍然大悟。

      一:n<=m。数据小于<1000,直接暴力

      二:n>m。

        首先明白这一点:如果两个数,a,b除以m的余数相同,那么它们的差是m的倍数!!!

        根据鸽巢原理,%m,那么存在余数m种,而n>m,那么必然存在两个数%m相同,那么它们的差,就是m的倍数。那么存在|a[i]-a[j]|%m==0,最终结果就是0

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
typedef long long ll;
const int maxn = 2e5+10;
ll a[maxn];
int main()
{
    int n, m ;
    cin>>n>>m;
    ll sum=1;
    for(int i=0;i<n;i++)
        cin>>a[i];
    if(n<=m)
    {
        for(int i=0;i<n;i++)
        {
            for(int j=i+1;j<n;j++)
            {
                ll mid=fabs(a[i]-a[j]);
                sum=sum*mid%m;
            }
        }
        cout<<sum<<endl;
    }
    else
        cout<<'0'<<endl;
}
原文地址:https://www.cnblogs.com/liyexin/p/12416912.html