Codeforces Round 486 Div3(包含前五题题解)

第一次打cf的div3耶,然后发现挺简单的,题目意思特别好懂,然后前三个题比较简单,其实第四题也简单,后两个题目稍微麻烦点,然后这次我只做了三题,第四题写完了结果没时间提交了,哎,还是不行,要继续加油啊。

A. Diverse Team
time limit per test
1 second
memory limit per test
256 megabytes
input
standard input
output
standard output

There are nn students in a school class, the rating of the ii-th student on Codehorses is aiai. You have to form a team consisting of kk students (1kn1≤k≤n) such that the ratings of all team members are distinct.

If it is impossible to form a suitable team, print "NO" (without quotes). Otherwise print "YES", and then print kk distinct numbers which should be the indices of students in the team you form. If there are multiple answers, print any of them.

Input

The first line contains two integers nn and kk (1kn1001≤k≤n≤100) — the number of students and the size of the team you have to form.

The second line contains nn integers a1,a2,,ana1,a2,…,an (1ai1001≤ai≤100), where aiai is the rating of ii-th student.

Output

If it is impossible to form a suitable team, print "NO" (without quotes). Otherwise print "YES", and then print kk distinct integers from 11 to nn which should be the indices of students in the team you form. All the ratings of the students in the team should be distinct. You may print the indices in any order. If there are multiple answers, print any of them.

Assume that the students are numbered from 11 to nn.

Examples
input
Copy
5 3
15 13 15 15 12
output
Copy
YES
1 2 5 
input
Copy
5 4
15 13 15 15 12
output
Copy
NO
input
Copy
4 4
20 10 40 30
output
Copy
YES
1 2 3 4 
Note

All possible answers for the first example:

  • {1 2 5}
  • {2 3 5}
  • {2 4 5}

Note that the order does not matter.

A题题意:给你一个序列,问你能否从中找到k个不同的数,那么就是一个大水题了,可以开一个数组记录,也可以用STL的set记录。

#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
#include<algorithm>
#include<list>
#define inf 0x3f3f3f3f
using namespace std;
typedef long long ll;
int judge[1005];
int main()
{
    int n,k;
    memset(judge,0,sizeof judge);
    cin>>n>>k;
    int item;
    vector<int> v;
    int cnt = 0;
    for( int i =1  ;i <= n ; i++ )
        {
            cin>>item;
            if( judge[item] == 0 )
            {
                cnt++;
                judge[item]=  1;
                v.push_back(i);    //记录答案
            }
        }
    if( cnt >= k )
    {
        cout<<"YES\n";
        for( int i = 0 ; i < k ; i++ )
        {
            if( i )
                cout<<" ";
            cout<<v[i];

        }
        cout<<endl;
    }
    else cout<<"NO\n";
    return 0;
}

B. Substrings Sort
time limit per test
1 second
memory limit per test
256 megabytes
input
standard input
output
standard output

You are given nn strings. Each string consists of lowercase English letters. Rearrange (reorder) the given strings in such a way that for every string, all strings that are placed before it are its substrings.

String aa is a substring of string bb if it is possible to choose several consecutive letters in bb in such a way that they form aa. For example, string "for" is contained as a substring in strings "codeforces", "for" and "therefore", but is not contained as a substring in strings "four", "fofo" and "rof".

Input

The first line contains an integer nn (1n1001≤n≤100) — the number of strings.

The next nn lines contain the given strings. The number of letters in each string is from 11 to 100100, inclusive. Each string consists of lowercase English letters.

Some strings might be equal.

Output

If it is impossible to reorder nn given strings in required order, print "NO" (without quotes).

Otherwise print "YES" (without quotes) and nn given strings in required order.

Examples
input
Copy
5
a
aba
abacaba
ba
aba
output
Copy
YES
a
ba
aba
aba
abacaba
input
Copy
5
a
abacaba
ba
aba
abab
output
Copy
NO
input
Copy
3
qwerty
qwerty
qwerty
output
Copy
YES
qwerty
qwerty
qwerty
Note

In the second example you cannot reorder the strings because the string "abab" is not a substring of the string "abacaba".

B题题意:给你n个字符串,然后你重新排一下他们的顺序,使得前面的字符串是后面所有字符串的子串(这里的子串是连续的)。

一开始,我还没有思路,因为不是特别喜欢做字符串的题目,但是后来看了那么多人做了,最后还是写了。

我们把每个字符串按照长度排序,然后从最长的字符串开始判断,因为最长的字符串不需要进行比较,它只需要被别人拿来比较,拿来作为参照。然后我们就从倒数第二个字符串,判断到最短的字符串,每次都是将当前字符串和前一个字符串相比,看是不是子串,(这里我是直接暴力比的,应该不会超时,其实可以用KMP优化),这个算法的复杂度大概是O(n^3),遍历所有的字符串O(n)乘以两个字符串相比O(n^n)。这里我觉得比较巧的地方就是,你排序之后,每次的字符串只需要和前一个相比就行了,不需要和前面所有的字符串进行比较。


#include<iostream>
#include<cstdio>
#include<vector>
#include<cstring>
#include<algorithm>
#include<string>
#include<map>
using namespace std;
int n;
struct spe
{
    char s[105];
    int len;
};
spe p[105];
bool cmp( spe a,spe b )
{
    return a.len > b.len;
}
bool check( char s1[],char s2[] )//s2 是 s1 的子串
{
    int len1 = strlen(s1);
    int len2 = strlen(s2);
    for( int i = 0 ; i < len1 ; i++ )
    {
        if( s1[i] == s2[0] )
        {
            int j = 0,k = i;
            while( s1[k] == s2[j] && k < len1 && j < len2 )
                j++,k++;
            if( j == len2 )
                return true;
        }
    }
    return false;
}
int main()
{
    scanf("%d",&n);
    for( int i = 1 ; i <= n ; i++ )
    {
        scanf("%s",p[i].s);
        p[i].len = strlen(p[i].s);
    }
    sort(p+1,p+1+n,cmp);
    bool flag = true;
    int len = p[1].len;
    for( int i = 2 ; i <= n ; i++ )
    {
        if( p[i].len == len )
        {
            if( strcmp(p[i-1].s,p[i].s) != 0 )    //如果两个字符串长度相等   那么他们必须相同
            {                                    //其实这个判断可以去掉,用下面的函数
                //cout<"ff";
                flag = false;
                break;
            }
        }
        else if( check(p[i-1].s,p[i].s ) == false )
        {
            //cout<<"ff";
            flag = false;
            break;
        }
        len = p[i].len;
    }
    if( flag )
    {
        printf("YES\n");
        for( int i = n ; i >= 1 ; i-- )
            printf("%s\n",p[i].s);
    }
    else printf("NO\n");
    return 0;
}

C. Equal Sums
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

You are given kk sequences of integers. The length of the ii-th sequence equals to nini.

You have to choose exactly two sequences ii and jj (iji≠j) such that you can remove exactly one element in each of them in such a way that the sum of the changed sequence ii (its length will be equal to ni1ni−1) equals to the sum of the changed sequence jj (its length will be equal to nj1nj−1).

Note that it's required to remove exactly one element in each of the two chosen sequences.

Assume that the sum of the empty (of the length equals 00) sequence is 00.

Input

The first line contains an integer kk (2k21052≤k≤2⋅105) — the number of sequences.

Then kk pairs of lines follow, each pair containing a sequence.

The first line in the ii-th pair contains one integer nini (1ni<21051≤ni<2⋅105) — the length of the ii-th sequence. The second line of the ii-th pair contains a sequence of nini integers ai,1,ai,2,,ai,niai,1,ai,2,…,ai,ni.

The elements of sequences are integer numbers from 104−104 to 104104.

The sum of lengths of all given sequences don't exceed 21052⋅105, i.e. n1+n2++nk2105n1+n2+⋯+nk≤2⋅105.

Output

If it is impossible to choose two sequences such that they satisfy given conditions, print "NO" (without quotes). Otherwise in the first line print "YES" (without quotes), in the second line — two integers iixx (1ik,1xni1≤i≤k,1≤x≤ni), in the third line — two integers jjyy (1jk,1ynj1≤j≤k,1≤y≤nj). It means that the sum of the elements of the ii-th sequence without the element with index xx equals to the sum of the elements of the jj-th sequence without the element with index yy.

Two chosen sequences must be distinct, i.e. iji≠j. You can print them in any order.

If there are multiple possible answers, print any of them.

Examples
input
Copy
2
5
2 3 1 3 2
6
1 1 2 2 2 1
output
Copy
YES
2 6
1 2
input
Copy
3
1
5
5
1 1 1 1 1
2
2 3
output
Copy
NO
input
Copy
4
6
2 2 2 2 2 2
5
2 2 2 2 2
3
2 2 2
5
2 2 2 2 2
output
Copy
YES
2 2
4 1
Note

In the first example there are two sequences [2,3,1,3,2][2,3,1,3,2] and [1,1,2,2,2,1][1,1,2,2,2,1]. You can remove the second element from the first sequence to get [2,1,3,2][2,1,3,2] and you can remove the sixth element from the second sequence to get [1,1,2,2,2][1,1,2,2,2]. The sums of the both resulting sequences equal to 88, i.e. the sums are equal.


C题题意:给你k个序列,找出两个序列出来,使他们每个去掉一个元素,sum和相等,(必须去掉一个),乍一看上去还挺难的哈。

仔细分析一下就有思路了,因为每个序列只能去掉一个元素,所以我们先把一个序列的sum求出来,然后遍历整个序列,记录去掉一个点后能够得到什么值。然后我们对每个序列做上述相同的操作。

其实,在做这些操作的过程时,就可以判断能不能满足条件了,即对于一个序列,如果去掉一个元素后的值出现过,那么就符合答案了,然后这个题还不能用数组记录出现的值,我用的是map,map<int,spe> spe是一个结构体,存的答案。我开始用的数组存的,一直过不了,因为题目sum的负数范围没有给。

#include<iostream>
#include<cstdio>
#include<vector>
#include<cstring>
#include<algorithm>
#include<map>
using namespace std;
int k,n;
const int maxn = 2e5+6;
int p[maxn];
struct spe
{
    int k,index;
};
map<int,spe> m;
int main()
{
    scanf("%d",&k);
    vector<int> ans;
    bool flag = false;
    for( int j = 1 ; j <= k ; j++ )
    {
        scanf("%d",&n);
        int sum = 0;
        for( int i = 1 ; i <= n ; i++ )
        {
            scanf("%d",&p[i]);
            sum += p[i];
        }
        //cout<<"dds";
        if( flag )
            continue;
        for( int i = 1 ; i <= n ; i++ )
        {
            int t = sum-p[i];
            if( m[t].k != j && m[t].index != 0 )
            {
                //cout<<"dd";
                ans.push_back(m[t].k);
                ans.push_back(m[t].index);
                ans.push_back(j);
                ans.push_back(i);
                flag = true;
                break;
            }
            else if( m[t].k == 0 )
            {
                m[t].k = j;
                m[t].index = i;
            }
        }
    }
    if( flag )
    {
        printf("YES\n");
        printf("%d %d\n",ans[0],ans[1]);
        printf("%d %d\n",ans[2],ans[3]);
    }
    else printf("NO\n");
    return 0;
}


D. Points and Powers of Two
time limit per test
4 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

There are nn distinct points on a coordinate line, the coordinate of ii-th point equals to xixi. Choose a subset of the given set of points such that the distance between each pair of points in a subset is an integral power of two. It is necessary to consider each pair of points, not only adjacent. Note that any subset containing one element satisfies the condition above. Among all these subsets, choose a subset with maximum possible size.

In other words, you have to choose the maximum possible number of points xi1,xi2,,ximxi1,xi2,…,xim such that for each pair xijxijxikxik it is true that |xijxik|=2d|xij−xik|=2d where dd is some non-negative integer number (not necessarily the same for each pair of points).

Input

The first line contains one integer nn (1n21051≤n≤2⋅105) — the number of points.

The second line contains nn pairwise distinct integers x1,x2,,xnx1,x2,…,xn (109xi109−109≤xi≤109) — the coordinates of points.

Output

In the first line print mm — the maximum possible number of points in a subset that satisfies the conditions described above.

In the second line print mm integers — the coordinates of points in the subset you have chosen.

If there are multiple answers, print any of them.

Examples
input
Copy
6
3 5 4 7 10 12
output
Copy
3
7 3 5
input
Copy
5
-1 2 5 8 11
output
Copy
1
8
Note

In the first example the answer is [7,3,5][7,3,5]. Note, that |73|=4=22|7−3|=4=22|75|=2=21|7−5|=2=21 and |35|=2=21|3−5|=2=21. You can't find a subset having more points satisfying the required property.

感觉是ACM里面挺好的一道签到题

题意是,从一个序列里面找几个数,使他们任意的两个数相减(取绝对值),都是2的倍数。

分析了半天,得出一个结论,最多只能取三个数

取到第四个数的时候,怎么搞都不能满足条件,比如说3,4,5  就在也找不到一个数了,有比如 4,6,8也是

然后算法思想是,遍历这个序列,对于每个数,加上2的倍数,看在这个序列里面有没有,最多加两次。

例如对于案例 

3 5 4 7 10 12

先排序    得 3 4 5 7 10 12

从3开始,加上1,发现里面有4, 然后4再加1,发现有5,(其实这时候答案已经出来了)。我们再把3加上2,发现有5,把5加上2,发现有7,(然后其实我们已经找到两组解了)。我们再把3加上4,得7,发现有7,再把7加上4,但是没有11。我们再把3加上8,得11,发现没有11。

接着我们到了4,然后分别对4 加上 1,2,4,8,16,一直加到超过最大的数。


#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<list>
#include<map>
#define inf 0x3f3f3f3f
using namespace std;
#define inf 0x3f3f3f3f
typedef long long ll;

const int maxn = 2e5+6;
int a[maxn];
int n;
map<int,int>  m;
int main()
{
    scanf("%d",&n);
    for( int i = 1 ; i <= n ; i++ )
    {
        scanf("%d",&a[i]);
        m[ a[i] ] = 1;
    }
    sort(a+1,a+1+n);
    int ans = 1;
    int first = a[1],gap;
    for( int i = 1 ; i <= n ; i++ )
    {
        int base = 1,cnt;
        while( base+a[i] <= a[n] )
        {
            cnt = 1;
            if( m[ a[i]+base ] )
            {
                if( m[ a[i]+(base<<1)] )
                {
                    ans = 3;
                    first = a[i];
                    gap = base;
                    goto there;
                }
                cnt = 2;
            }
            if( cnt > ans )
            {
                ans = cnt;
                first = a[i];
                gap = base;
            }
            base = base<<1;
        }
    }
    there:
    printf("%d\n",ans);
    printf("%d",first);
    for( int i = 2 ; i <= ans ; i++,first = first+gap )
        printf(" %d",first+gap);
    printf("\n");
    return 0;
}

E. Divisibility by 25
time limit per test
1 second
memory limit per test
256 megabytes
input
standard input
output
standard output

You are given an integer nn from 11 to 10181018 without leading zeroes.

In one move you can swap any two adjacent digits in the given number in such a way that the resulting number will not contain leading zeroes. In other words, after each move the number you have cannot contain any leading zeroes.

What is the minimum number of moves you have to make to obtain a number that is divisible by 2525? Print -1 if it is impossible to obtain a number that is divisible by 2525.

Input

The first line contains an integer nn (1n10181≤n≤1018). It is guaranteed that the first (left) digit of the number nn is not a zero.

Output

If it is impossible to obtain a number that is divisible by 2525, print -1. Otherwise print the minimum number of moves required to obtain such number.

Note that you can swap only adjacent digits in the given number.

Examples
input
Copy
5071
output
Copy
4
input
Copy
705
output
Copy
1
input
Copy
1241367
output
Copy
-1
Note

In the first example one of the possible sequences of moves is 5071  5701  7501  7510  7150.

E题一开始我一看,觉得好简单,然后瞬间就有思路了,但是没想到有太多的问题要考虑。


#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#define inf 0x3f3f3f3f
using namespace std;
typedef long long ll;

ll n;
vector<int> judge[14];
int main()
{
    scanf("%I64d",&n);
    if( n%25 == 0 )
    {
        printf("0\n");
        return 0;
    }
    ll t = n;
    int p[30];
    int cnt = 0;
    while( t )
    {
        p[++cnt] = t%10;
        t = t/10;
    }
    int ans = inf;
    if( cnt == 2 )
    {
        int a = n/10,b = n%10;
        if( b != 0 && (b*10+a)%25 == 0 )
            ans = 1;
        goto there;
    }
    for( int i = 1 ; i <= cnt ; i++ )
    {
        if( i == cnt )
        {
            if( p[i-1] == 0 )
            {
                if( p[i] == 5 ) //5 0 的情况,找找一个数替换0
                {
                    int j = i-1;
                    while( p[j] == 0 && j >= 1 )
                        j--;
                    if( j >= 1 )
                    {
                        if( judge[0][0] > j )
                            ans = min(ans,i-1-j+i+judge[0][0]-4);   //5 0
                        else ans = min(ans,i-1-j+i+judge[0][0]-3);
                        if( p[j] != 2 && p[j] != 7 )
                        {
                            if( judge[2].size() )
                                ans = min(ans,i-1-j+i+judge[2][0]-2);
                            if( judge[7].size() )
                                ans = min(ans,i-1-j+i+judge[7][0]-2);
                        }
                        else if( p[j] == 2 )
                        {
                            if( judge[2].size()+judge[7].size() <= 1 )
                            {
                                int k = j-1;
                                while( p[k] == 0 && k >= 1 )
                                    k--;
                                if( k >= 1 )
                                {
                                    ans = min(ans,i-1-k+i+judge[2][0]-3);//500024
                                }
                            }
                            else if( judge[2].size() >= 2 )
                                ans = min(ans,i-1-j+i+judge[2][0]-2);   //5024642
                            if( judge[7].size() )
                                ans = min(ans,i-1-j+i+judge[7][0]-2);   // 502467
                        }
                        else if( p[j] == 7 )
                        {
                            if( judge[7].size() == 1 && judge[2].size() == 0 )
                            {
                                int k = j-1;
                                while( p[k] == 0 && k >= 1 )
                                    k--;
                                if( k >= 1 )
                                    ans = min(ans,i-1-k+i+judge[7][0]-3);   //50074
                            }
                            else if( judge[7].size() >= 2 )
                                ans =  min(ans,i-1-j+i+judge[7][0]-2);  //50774
                            if( judge[2].size() )
                                ans = min(ans,i-1-j+i+judge[2][0]-2);   //507442
                        }
                    }
                }
                if( p[i] == 2 || p[i] == 7 )
                {
                    int j = i-1;
                    while( p[j] == 0 && j >= 1 )
                        j--;
                    if( j >= 1 )
                    {
                        if( p[j] != 5 )
                        {
                            if( judge[5].size() )
                                ans = min(ans,i-1-j+i+judge[5][0]-3);
                        }
                        else
                        {
                            if( judge[5].size() == 1 )
                            {
                                int k = j-1;
                                while( p[k] == 0 && k >= 1 )
                                    k--;
                                if( k >= 1 )
                                {
                                    ans = min(ans,i-1-k+i+judge[5][0]-4);
                                }
                            }
                            else ans = min(ans,i-1-j+i+judge[5][0]-3);
                        }
                    }
                }


            }
            else
            {
                if( p[i] == 2 || p[i] == 7 )
                {
                    if( judge[5].size() )
                        ans = min(ans,i+judge[5][0]-3);
                }
                else if( p[i] == 5 )
                {
                    if( judge[0].size() )
                        ans = min(ans,i+judge[0][0]-3);
                    if( judge[2].size() )
                        ans = min(ans,i+judge[2][0]-2);
                    if( judge[7].size() )
                        ans = min(ans,i+judge[7][0]-2);
                }
            }
            break;
        }
        if( p[i] == 0 )
        {
            judge[0].push_back(i);
            if( judge[0].size() == 2 )
                ans = min( ans,judge[0][0]+i-3 );
            if( judge[5].size() )
                ans = min( ans,judge[5][0]+i-2);
        }
        else if( p[i] == 5 )
        {
            judge[5].push_back(i);
            if( judge[2].size() )
                ans = min(ans,judge[2][0]+i-2);
            if( judge[0].size() )
                ans = min( ans,judge[0][0]+i-3);
            if( judge[7].size() )
                ans = min( ans,judge[7][0]+i-2);
        }
        else if( p[i] == 2 )
        {
            judge[2].push_back(i);
            if( judge[5].size() )
                ans = min( ans,judge[5][0]+i-3);
        }
        else if( p[i] == 7 )
        {
            judge[7].push_back(i);
            if( judge[5].size() )
                ans = min( ans,judge[5][0]+i-3);
        }
        //if( ans == 2 )
           // cout<<"asd"<<i<<endl;
    }
    there:
    if( ans == inf )
        printf("-1\n");
    else printf("%d\n",ans);
    return 0;
}

/*
500024
50030
50003
5003000

*/
最后一个题我就不写了,时间有限,大家见谅

猜你喜欢

转载自blog.csdn.net/qq_39627843/article/details/80549498
今日推荐