AtCoder Beginner Contest 170

A

给一个数列[1...5]其中有一位是错误的,错误位置是0,问哪一位错误

#include <bits/stdc++.h>
using namespace std;

int main()
{
    for( int i = 1 , x ; i <= 5 ; i ++ )
    {
        cin >> x;
        if( x == i ) continue;
        cout << i << endl;
        return 0;
    }
}

B

鸡兔同笼

鹤有两只腿,龟有四只腿。现有x个头y只腿,问时候合理

#include <bits/stdc++.h>
using namespace std;

int main()
{
    int a , b;
    cin >> a >> b;
    for( int i = 0 , j ; i <= a ; i ++ )
    {
        j = a - i;
        if( 2 * i + 4 * j == b )
        {
            cout << "Yes" << endl;
            return 0;
        }
    }
    cout << "No" << endl;
    return 0;
}

C

给一个数列p长度为n,问最接近k且不在p中的数,若同时存在两个输出小的

#include <bits/stdc++.h>
using namespace std;


int n , k;
bool v[105];


int main()
{
    cin >> k >> n;
    for( int i = 1 , x ; i <= n ; i ++ )
    {
        cin >> x;
        v[x] = 1;
    }
    for( int i = 0 ; i <= 100 ; i ++ )
    {
        if( k - i >= 0 )
        {
            if( v[ k - i ] == 0 )
            {
                cout << k - i << endl;
                return 0;
            }
        }
        if( v[ k + i ] == 0 )
        {
            cout << k + i << endl;
            return 0;
        }
    }
    return 0;
}

D

给以一个长度为n的数列a,问有多少数不能被数列中其他任意数整除

考虑类似埃拉斯托利瑟筛法

首先排序,然后每一个没有被筛过的数去筛别的数,可以用二分查找该数的倍数

但没有被筛过的数不一定就是答案比如5 5 15 虽然第二个5没有被筛掉,但是他依旧可以被第一个5整除,所以还有判断下一位数是否和该数相同。若相同两数均不可。

#include <bits/stdc++.h>
using namespace std;

const int N = 2e5 + 5;
int n , cnt , a[N];
bool v[N];
map< int , int > ju;


inline int read()
{
    int x = 0;
    char ch = getchar();
    while( ch < '0' || ch > '9' ) ch = getchar();
    while( ch >= '0' && ch <= '9' ) x = ( x << 3 ) + ( x << 1 ) + ch - '0' , ch = getchar();
    return x;
}

int main()
{
    n = read();
    for( int i = 1 ; i <= n ; i ++ ) a[i] = read();
    sort( a + 1 , a + 1 + n );
    for( int i = 1 ; i <= n ; i ++ )
    {
        if( v[i] ) continue;
        if( a[i] == a[ i + 1 ] )
        {
            for( int j = i ; j <= n ; j ++ )
            {
                if( a[i] != a[j] ) break;
                v[j] = 1;
            }
        }
        else cnt ++;
        for( int j = 1 ; j * a[i] <= a[n] ; j ++ )
        {
            int k = lower_bound( a + 1, a + 1 + n , a[i] * j ) - a;
            while( a[k] == a[i] * j ) v[k] = 1 , k ++;
        }
    }
    cout << cnt << endl;
    return 0;
}

第二种做法

用桶代替了二分查找

#include<bits/stdc++.h>
using namespace std;

const int N = 1e6 + 5;
int n , cnt , a[N] , v[N] , m = -1;

int main()
{
    cin >> n ;
    for( int i = 1 , x ; i <= n ; i ++ )
    {
        cin >> x;
        m = max( m , x );
        a[x] ++;
    }
    for( int i = 1 ; i <= m ; i ++ )
    {
        if( a[i] == 0 || v[i] ) continue;
        if( a[i] == 1 )  cnt ++;
        for( int j = 2 ; j * i <= m ; j ++ ) v[ i * j ] = 1;
    }
    cout << cnt << endl;
    return 0;
}

E

给定多个集合,每次将一个集合中的一个数移动到另一个集合中,问每次操作后所有集合的最大值的最小值

可以用multiset来模拟这个过程,每个集合各用一个multiset维护,将所有集合的最大值再用一给个multiset维护,每次删除和插入的时候判断是是否是该集合的最大值来考虑是否修改最大值的集合

#include <bits/stdc++.h>
using namespace std;

const int N = 2e5 + 5;
int n , cnt , a[N];
bool v[N];
map< int , int > ju;


inline int read()
{
    int x = 0;
    char ch = getchar();
    while( ch < '0' || ch > '9' ) ch = getchar();
    while( ch >= '0' && ch <= '9' ) x = ( x << 3 ) + ( x << 1 ) + ch - '0' , ch = getchar();
    return x;
}

int main()
{
    n = read();
    for( int i = 1 ; i <= n ; i ++ ) a[i] = read();
    sort( a + 1 , a + 1 + n );
    for( int i = 1 ; i <= n ; i ++ )
    {
        if( v[i] ) continue;
        if( a[i] == a[ i + 1 ] )
        {
            for( int j = i ; j <= n ; j ++ )
            {
                if( a[i] != a[j] ) break;
                v[j] = 1;
            }
        }
        else cnt ++;
        for( int j = 1 ; j * a[i] <= a[n] ; j ++ )
        {
            int k = lower_bound( a + 1, a + 1 + n , a[i] * j ) - a;
            while( a[k] == a[i] * j ) v[k] = 1 , k ++;
        }
    }
    cout << cnt << endl;
    return 0;
}
posted @ 2021-10-24 21:59  PHarr  阅读(108)  评论(0编辑  收藏  举报