1. 程式人生 > 其它 >atcoder ABC 170 部分題解

atcoder ABC 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 >= 1 )
        {
            if( v[ k - i ] == 0 )
            {
                cout << k - i << endl;
                return 0;
            }
        }
        if( k + i <= 100 )
        {
            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;
}

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