미국에서 고등학생들을 대상으로 하는 올림피아드 중에서 준비하는 사람들의 성격이 비슷할 것 같은 두가지에 대해서 확인한 몇가지 자료를 가지고 어떤 차이가 있고, 왜 그런 차이가 있을까 생각해봤다.

 

먼저, 2 가지 모두 몇번의 선발과정을 거쳐서 상위 득점자들이 모여서 다음 단계를 진행한다.

 

USAMO 는 다음과 같은 순서로 진행된다.

  1. AMC10 / AMC12 : 누구나 참가 가능
  2. AIME : 1의 시험에서 상위 득점자
  3. USAMO / USAJMO : 1+2 시험의 상위 득점자 500 명
  4. MOP : 3의 상위 득점자 60명 내외
  5. IMO : 4 + @

USACO 의 경우

  • Dec, Jan, Feb, Mar 4 회의 online test
  • bronze - silver - gold - platinum 단계별 승급
  • Summer camp : platinum 상위 득점자
  • IOI : 4 + @

2019-2020 의 경우 자료가 다 나오지 않아서, 2018-2019 자료를 기준으로 분석했다.

 

USAMO 

AMC10A AMC12A AMC10B AMC12B AIME A AIME B USAMO
38386 31285 21093 16786 2731 1226 500

미국내 참가자 만을 대상으로 한 결과이다.

 

USACO 

  All/USA Platinum Gold Silver Bronze
All Pre-C All Pre-C All Pre-C All Pre-C
`18 Dec 5290/2882 458 319 842 672 1967 1614 3784 3103
`19 Jan 4953/2623 525 380 988 812 1826 1511 2537 2037
`19 Feb 4317/2261 451 349 874 734 1067 900 2162 1707
`19 Mar 2993/1431 410 319 661 572 831 685 1288 972

레벨에 따른 참가자 분포가 달라질 수 있지만, 단순히 전체 참가자 중에서 미국 참가자수를 기준으로 하면, 전체 참가자의 50%정도가 미국내 참가자 이다.

  Gold -> Platinum Silver -> Gold Bronze -> Silver
`18 Dec 34 64 853
`19 Jan 53 452 306
`19 Feb 18 29 139
`19 Mar 21 51 88

Bronze 레벨 참가자는 AMC10/AMC12 참가자와 비슷한 위치에 있다. 

AMC10/12 는 2번의 시험이고 중복 참가가 가능하므로 대략 70000명 정도가 참가한다고 할 수 있다. (AMC10A+AMC12A) Bronze 레벨 참가자의 1/2을 미국 참가자라고 하면, 1500 명정도라고 할 수 있겠다. 4번의 시험동안 추가 유입이 가능하지만, 실제로 참가자수는 매번 줄어든다. 이 줄어드는 참가자들은 다음 단계로 승급된 경우도 있지만, 그냥 포기한 경우도 있을 것이다.  `18 12월 bronze 참가자 중에 Pre-C는 3103명이며, 이중 50%가 미국내 참가자라고 하면, 이중에 1550명이고 이중 853명이 승급되었으므로 참가자는 700명남고 1월에 참가자는 1000명정도에 300명이 승급되면, 다시 700명정도가 남는다. 다음인 2월에는 850/139 ~ 700, 3월에는 480/88 정도라고 할 수 있다.

 

1500 명 vs. 70000 명. 40배 이상의 차이가 된다. 왜 이런 차이가 나타난 것일까? USACO가 USAMO보다 알려진 기간이 짧아서인것도 한가지 이유가 될 테고, 학교에서 기본으로 배우는 수학과 개인이 추가로 배워야 하는 프로그래밍이라는 차이도 한가지 이유가 될 것이다.

 

또다른 차이라고 생각한 것은 2가지 시험을 위해서 준비하는 방향성 혹은 방법의 차이가 있는 것 같다. USAMO를 준비하는 학생들은 대부분이 4~6학년 사이에 AMC8으로 시작해서 AMC10/AMC12를 준비한다. 이 과정에서 학생들은 거의 표준화된 교재들을 순서대로 공부하고, 필요에 따라서 개인적인 추가 수업을 받기도 하면서 준비한다. 하지만, USACO를 준비하기 위해서는 특별히 알려져 있는 준비과정이 없다. 또, 프로그래밍은 새로운 언어를 배우는 것과 닮아 있어서 개인의 역량에 크게 영향을 받는다. 어떤 사람은 단순히 입문 교재만을 읽어보고도 충분한 정보를 습득해서, 자기가 원하는 프로그램을 작성할 수 있지만, 어떤 사람은 모든 과정에 익숙해지기 전에는 작은 프로그램도 못 만드는 경우도 있다. 여기에 더해서, Competitive Programming 이라고 하는, 이런 대회를 준비하는 것은 일반 프로그래밍을 배우는 것과는 또 다른 방향으로 접근해야한다. 

 

이런 것이 참가자 수의 현격한 차이를 만든 이유라고 생각한다.  다음에는 USACO 와 USAMO 시험에 대해서 조금은 다른 방향으로 한번 생각해보려고 한다. 두 가지는 어떤 방향성을 가지고 준비해야 하는가? 혹은 어떤 것이 준비에 더 어려운가? 준비를 위해 더 효과적인 방법은 없을까? 여러가지 방향으로 생각들을 정리해서 적어보겠다.

 

'Basic Preparation' 카테고리의 다른 글

USAMO vs USACO III  (0) 2020.04.16
USAMO vs USACO II  (0) 2020.04.09
Teach Yourself C++  (0) 2019.09.17
C++ 공부 - 2019. 8월  (0) 2019.09.02
2019년 8월 진행  (0) 2019.08.24

출처: https://train.usaco.org/usacogate


문제 설명

Farmer John prides himself on having the healthiest dairy cows in the world. He knows the vitamin content for one scoop of each feed type and the minimum daily vitamin requirement for his cows. Help Farmer John feed the cows so they stay healthy while minimizing the number of scoops that a cow is fed.
Given the daily requirements of each kind of vitamin that a cow needs, identify the smallest combination of scoops of feed a cow can be fed in order to meet at least the minimum vitamin requirements.
Vitamins are measured in integer units. Cows can be fed at most one scoop of any feed type. It is guaranteed that a solution exists for all contest input data.

입력

Line 1: integer V (1 <= V <= 25), the number of types of vitamins

Line 2: V integers (1 <= each one <= 1000), the minimum requirement for each of the V vitamins that a cow requires each day

Line 3: integer G (1 <= G <= 15), the number of types of feeds available

Lines 4..G+3:
V integers (0 <= each one <= 1000), the amount of each vitamin that one scoop of this feed contains. The first line of these G lines describes feed #1; the second line describes feed #2; and so on.

출력

The output is a single line of output that contains:
 - the minimum number of scoops a cow must eat, followed by:
 - a SORTED list (from smallest to largest) of the feed types the cow is given

입력 예

4
100 200 300 400
3
50 50 50 50
200 300 200 300
900 150 389 399

출력 예

2 1 3


문제 풀이

모든 feed를 한번씩만 줄 수 있으므로, 전체 feed에서 가능한 모든 조합을 찾아서, 최소화 되는 조합을 출력한다.  feed 의 종류가 많지 않으므로( <= 15), bitset을 이용해서 필요한 조합을 찾는다. bitset<16> (0), ... bitset<16> (1<<numG) 다만, bitset으로 설정된 조합에서 작은 수들이 먼저 나오는 조합은 숫자로 변경하면, 더 큰 수가 된다.

프로그램 내용

더보기
...    
    for(int idx=0; idx < (1<<numG) ; ++idx)
    {
        vector <int> feeds(numV, 0);
        bitset<16> check(idx);

        for (int idx2=0; idx2 < numG ; ++idx2)
        {
            if( check[idx2] )
            {
                for(int idx3=0; idx3 < numV; ++idx3)
                {
                    feeds[idx3] += Feed_list[idx2][idx3];
                }
            }
        }

        /// check health : feeds vs V_req
        bool healthy = true;
        for(int idx2=0; idx2 < numV; ++idx2)
        {
            if ( feeds[idx2] < V_req[idx2])
            {
                healthy = false;
                break;
            }
        }

        if ( healthy 
        			&& check.count() < feed_count 
        			&& check.to_ulong() > feed_bit.to_ulong())
        {
            feed_count = check.count();
            feed_bit = check;
        }
    }
...

 

Chapter 2. Bigger Challenges (link)

USACO Training Site problems ( link )

 

Section 6.1  All tasks 
section 6.1.1 PROB Postal Vans 
section 6.1.2 PROB A Rectangular Barn 
section 6.1.1 PROB Cow XOR 

Section 6.2  All tasks 
section 6.2.1 PROB Calf Flac 
section 6.2.2 PROB Packing Rectangles 
section 6.2.3 PROB Shaping Regions 

Section 6.3 All tasks 
section 6.3.1 PROB Fence Rails 
section 6.3.2 PROB Cryptcowgraphy 

Section 6.4 All tasks 
section 6.4.1 PROB The Primes 
section 6.4.2 PROB Electric Fences 
section 6.4.3 PROB Wisconsin Squares 

Section 6.5 All tasks  
section 6.5.1 PROB All Latin Squares 
section 6.5.2 PROB Closed Fences 
section 6.5.3 PROB Betsy's Tour 
section 6.5.4 PROB The Clocks 
section 6.5.5 PROB Checker Challenge 

USACO Training Site problems (link)

 

Chapter 5  Serious challenges
Section 5.1 Convex Hulls 
section 5.1.1 TEXT Convex Hulls
section 5.1.2 PROB Fencing the Cows 
section 5.1.3 PROB Starry Night 
section 5.1.4 PROB Musical Themes 

Section 5.2 All tasks 
section 5.2.1 PROB Snail Trail 

Section 5.3 Heuristics 
section 5.3.1 TEXT Heuristics & Approximate Searches
section 5.3.2 PROB Milk Measuring 
section 5.3.3 PROB Window Area 
section 5.3.4 PROB Network of Schools 
section 5.3.5 PROB Big Barn 

Section 5.4 All tasks
section 5.4.1 PROB Canada Tour 
section 5.4.2 PROB Character Recognition 
section 5.4.3 PROB TeleCowmunication 

Section 5.5 All tasks 
section 5.5.1 PROB Picture 
section 5.5.2 PROB Hidden Passwords 
section 5.5.3 PROB Two Five 

USACO Training Site problems (link)

 

Chapter 4. Advanced algorithms and difficult drills

Section 4.1 Optimization
section 4.1.1 Optimization Techniques
section 4.1.2 PROB Beef McNuggets 
section 4.1.3 PROB Fence Loops 

Section 4.2 Network Flow
section 4.2.1 TEXT "Network Flow" Algorithms
section 4.2.2 PROB Drainage Ditches 
section 4.2.3 PROB The Perfect Stall 
section 4.2.4 PROB Job Processing 

Section 4.3 Bignums 
section 4.3.1 TEXT Big Numbers
section 4.3.2 PROB Buy Low, Buy Lower 
section 4.3.3 PROB Street Race 
section 4.3.4 PROB Letter Game 

 

Section 4.4  All tasks 
section 4.4.1 PROB Shuttle Puzzle 
section 4.4.2 PROB Pollutant Control 
section 4.4.3 PROB Frame Up 

USACO Training Site problems ( link )

 

Chapter 3 Techniques more subtle

Section 3.1 Spanning Trees
section 3.1.1 TEXT Minimal Spanning Trees
section 3.1.2 PROB Agri-Net
section 3.1.3 PROB Score Inflation
section 3.1.4 PROB Humble Numbers
section 3.1.5 PROB Contact
section 3.1.6 PROB Stamps

Section 3.2 Knapsack
section 3.2.1 TEXT Knapsack Problems
section 3.2.2 PROB Factorials
section 3.2.3 PROB Stringsobits 
section 3.2.4 PROB Spinning Wheels
section 3.2.5 PROB Feed Ratios 
section 3.2.6 PROB Magic Squares 
section 3.2.7 PROB Sweet Butter 


Section 3.3 Eulerian Tours
section 3.3.1 TEXT Eulerian Tours
section 3.3.2 PROB Riding The Fences 
section 3.3.3 PROB Shopping Offers 
section 3.3.4 PROB Camelot 
section 3.3.5 PROB Home on the Range 
section 3.3.6 PROB A Game 

Section 3.4 Computational Geometry
section 3.4.1 TEXT Computational Geometry
section 3.4.2 PROB American Heritage 
section 3.4.3 PROB Electric Fence 
section 3.4.4 PROB Raucous Rockers 

처음 풀이 ( link )


문제 풀이

자물쇠 숫자 3개를 tuple<int, int, int>로 처리하고, 숫자 사이의 차이를 abs 이용해서 계산한다. 다만, modulo 연산에서 -를 지원하지 않기 때문에 dial number - 2 ( modulo -2) 보다 큰 경우도 고려한다. 3중 루프를 O(N^3)이지만 최대 dial number 100 을 생각하면, 속도에 문제가 될 것 같지는 않다. 필요하다면, key number 에서 5x5x5 로 가능한 숫자 배열을 작성하고, 그 배열 숫자들로만 루프를 돌리면 좀 더 빨라질 것 같다. 중복 제거를 위해서 set 에 무조건 입력하고, 중복이 제거된 결과의 수만 조회 했는데, 입력하기 전에 조회를 하고 없으면 입력하도록 하는것도 방법이 될 수는 있을 것 같다. 효율성은 find를 하고 없으면 입력하는것이 조금은 더 좋을 것 같다.

프로그램 내용

더보기
#define MAX_DIAL 100

/// tuple<int, int, int> key vs tuple<int, int, int> dest check
bool check_distance(tuple <int, int, int> key, tuple <int, int, int> dest, int dial_num);
{
    int a, b, c;
    int x, y, z;
    tie(a,b,c) = key;
    tie(x,y,z) = dest;
    int dist1, dist2, dist3;

    dist1 = abs(a-x);    dist2 = abs(b-y);    dist3 = abs(c-z);

    if ((dist1 <= 2 || dist1 >= dial_num-2)
        && (dist2 <= 2 || dist2 >= dial_num-2)
        && (dist3 <= 2 || dist3 >= dial_num-2) )
        return true;
    else
        return false;
}

int main() {
    /// Read requirement
    int dial_num = 0;
    fin >> dial_num;

    int f1, f2, f3;
    fin>> f1 >> f2 >> f3;

    int m1, m2, m3;
    fin>> m1 >> m2 >> m3;

    set <tuple<int,int,int>> c_codes;

    tuple <int, int, int> f_key = make_tuple(f1, f2, f3);
    tuple <int, int, int> m_key = make_tuple(m1, m2, m3);

    for(int id1=0;id1 < dial_num ; ++id1)
        for (int id2 = 0; id2 < dial_num; ++id2)
            for(int id3= 0; id3 < dial_num; ++id3)
                tuple <int, int, int> c_key = make_tuple(id1, id2, id3);
                /// check distance 1d1 with f1/m1, id2 with f2/m2, id3 with f3/m3
                if(check_distance(f_key, c_key, dial_num))
                    c_codes.insert(c_key);
                if(check_distance(m_key, c_key, dial_num))
                    c_codes.insert(c_key);

    if (dial_num < 6)
        fout << dial_num * dial_num * dial_num << endl;
    else
        fout << c_codes.size() << endl;

 

 

Chapter 1. Getting started (link)

출처: https://train.usaco.org/usacogate


문제 설명

Farmer John has three milking buckets of capacity A, B, and C liters. Each of the numbers A, B, and C is an integer from 1 through 20, inclusive. Initially, buckets A and B are empty while bucket C is full of milk. Sometimes, FJ pours milk from one bucket to another until the second bucket is filled or the first bucket is empty. Once begun, a pour must be completed, of course. Being thrifty, no milk may be tossed out. 

Write a program to help FJ determine what amounts of milk he can leave in bucket C when he begins with three buckets as above, pours milk among the buckets for a while, and then notes that bucket A is empty.

입력 

A single line with the three integers A, B, and C.

출력

A single line with a sorted list of all the possible amounts of milk that can be in bucket C when 
bucket A is empty.

입력 예

8 9 10

출력 예

1 2 8 9 10


문제 풀이

water jug problem 이라고 불리는 물통 사이에서 물을 옮기는 문제이다. 여기서는 물통 3개를 이용하므로, 3 water jug problem이라고 할 수 있다. 시작할때 가지고 있는 물의 양(0, 0, C)에서 물통 사이에서 한번에 옮길 수 있는 6가지 경우들을 재귀적으로 검색한다. 한번 검색한 곳은 다시 검색하지 않도록 확인해서, 검색을 종료하도록 한다. 문제 조건에 따라서 물통 A가 비어 있을때 물통 C의 양을 기록해서 출력한다.

프로그램 내용

더보기
#define BUCKET_LIMIT 21

vector <int> record(BUCKET_LIMIT, 0); /// possible amount record
vector <vector <int>> visited(BUCKET_LIMIT, vector<int>(BUCKET_LIMIT,0)); /// mark visit
vector <int> capa(3); /// store bucket status

void pour(int &from, int &to, int cpfrom, int cpto);
void search(int a, int b, int c); /// check all possible case

int main() {
    int A, B, C;
    fin >> A >> B >> C;

/// initial
    /// Bucket A : 0, Bucekt B: 0, Bucket C: full
    capa[0] = A;    capa[1] = B;    capa[2] = C;

    search(0, 0, C);

 

Chapter 1. Getting started ( link )

출처: https://train.usaco.org/usacogate


문제 설명

The cows have not only created their own government but they have chosen to create their own money system. In their own rebellious way, they are curious about values of coinage. Traditionally, coins come in values like 1, 5, 10, 20 or 25, 50, and 100 units, sometimes with a 2 unit coin thrown in for good measure.
The cows want to know how many different ways it is possible to dispense a certain amount of money using various coin systems. For instance, using a system of {1, 2, 5, 10, ...} it is possible to create 18 units several different ways, including: 18x1, 9x2, 8x2+2x1, 3x5+2+1, and many others.
Write a program to compute how many ways to construct a given amount of money using supplied coinage. It is guaranteed that the total will fit into both a signed long long (C/C++) and Int64 (Free Pascal).

입력 양식

The number of coins in the system is V (1 <= V <= 25).
The amount money to construct is N (1 <= N <= 10,000).

Line 1: Two integers, V and N
Lines 2..: V integers that represent the available coins (no particular number of integers per line)

출력

A single line containing the total number of ways to construct N money units using V coins.

입력 예

3 10 
1 2 5

출력 예

10


문제 풀이

특정한 정수 집합으로 원하는 값을 만들어내는 경우의 수를 세는 문제로 coin change 문제이다. 

특정한 코인 값 c[i] =a 라고 하면, 원하는 값 target 를 만들 수 있는 방법은 이 코인이 없이 만들수 있는 경우의 수와 이 코인 값을 제외한 값을 만들수 있는 경우의 수의 합이 된다. 

  ... target - b  ... target ...
coin[i] = a ... ... ... v(target, a) ...
coin[i+1] = b ... v(target - b, b) ... v(target, b) ...

 v(target, b) = v(target, a) + v(target-b, b) 

다만, 이 경우에는 코인의 수는 제한이 없기 때문에, 코인 값의 배수들에 해당하는 값들을 모두 확인해야 한다.

참고: subset sum problem ( link )

프로그램 내용

더보기
int main()
{
    int N, target;
    fin >> N >> target;

    vector<int> coins(N,0);

    for (int id = 0; id < N; ++id) 
        fin >> coins[id]; 

    vector <long long> table(target+1,0);

    sort(coins.begin(), coins.end());

    table[0] = 1;

    for(int id = 0; id < N; ++id) 
        for(int idn = coins[id]; idn <= target; ++idn) 
            table[idn] += table[idn-coins[id]]; 

	if( table[target] != 0) 
        fout << table[target] << '\n'; 
    else 
        fout << -1 << '\n'; 

 

Chapter 2. Bigger Challenges ( link )

'USACO Training' 카테고리의 다른 글

Problem 1.4.6 Combination Lock - 2  (0) 2019.10.13
Problem 1.5.3 Mother's Milk  (0) 2019.10.12
Problem 2.2.4 Subset Sums  (0) 2019.10.10
Problem 2.1.5 Sorting A Three-Valued Sequence  (0) 2019.09.18
Problem 2.1.4 Ordered Fractions  (0) 2019.09.18

출처: https://train.usaco.org/usacogate


문제 설명

For many sets of consecutive integers from 1 through N (1 <= N <= 39), one can partition the set into two sets whose sums are identical. 

For example, if N=3, one can partition the set {1, 2, 3} in one way so that the sums of both subsets
are identical:

  • {3} and {1,2}

This counts as a single partitioning (i.e., reversing the order counts as the same partitioning and
thus does not increase the count of partitions).
If N=7, there are four ways to partition the set {1, 2, 3, ... 7} so that each partition has the same
sum:

  • {1,6,7} and {2,3,4,5}
  • {2,5,7} and {1,3,4,6}
  • {3,4,7} and {1,2,5,6}
  • {1,2,4,7} and {3,5,6}

Given N, your program should print the number of ways a set containing the integers from 1 through N can be partitioned into two sets whose sums are identical. Print 0 if there are no such ways. 


Your program must calculate the answer, not look it up from a table.

입력 

The input file contains a single line with a single integer representing N, as above.

출력 

The output file contains a single line with a single integer that tells how many same-sum partitions can be made from the set {1, 2, ..., N}. The output file should contain 0 if there are no ways to make a same-sum partition.

입력 예

7

출력 예

4


문제 풀이 내용

{1, 2, ..., N} 인 집합을 합이 같은 2개의 집합으로 나누는 경우의 수를 구하는 문제이다. 전체의 합은 N*(N+1)/2 이고 이것을 2개의 같은 값으로 나누는 것이기 때문에 N*(N+1)/4 = k. 즉, N % 4 = 0 or -1(3) 인 경우만 가능하다. 

이 경우의 수는 조건에 맞는 모든 부분집합을 찾아서 그 수를 구할 수 있다. N = 4K 인 경우는 A = { (1, 4), (5,8), ..., (4K+1, 4K+4)}, B = { (2, 3), (6,7), ... , (4K+2, 4K+3)} 의 두 집합으로 나눈뒤 한쪽의 특정한 값을 가진 수의 조합을 다른 쪽에서 같은 값을 가진 조합으로 변경해서, 다른 집합들을 찾을 수 있다. N = 4K+3 인 경우는 A = { (1,2), (5,5), ... (4K+1, 4K+2)}, B = { (0,3), (4, 7), ... , (4K, 4K+3)}으로 초기 집합을 나눌 수 있다.

 

부분 집합들을 직접 찾지 않고, 아래 같은 규칙을 이용해서 경우의 수를 세는 것도 가능하다.  다만 어떤 부분 집합이 가능한지는 알 수 없다.

 

  ... ... ... N*(N+1)/4 = K ...
{1, 2, ..., i} ... ... ... A(i, K) ...
{1, 2, ..., i+1} ... A(i+1, K-(i+1)) ... A(i+1, K) ...

A(i+1, K) 의 값은 새로운 수 (i+1)이 원하는 합을 만드는데 사용한 경우< A(i+1, K-(i+1))>와 사용하지 않는 경우<A(i, K)>의 합이 된다.  A(i+1, K) = A(i, K) + A(i+1, K-(i+1))

이 값들을 구하는데,  A(0,0) = 1. (empty set), A(k, 0) = 1(empty set) 을 가지고 시작해서 완성한다.

프로그램 내용

더보기
int main()
{
    unsigned long N;
    fin >> N;
    if( N % 4 == 1 || N % 4 == 2)
        fout << "0" << endl;

    int sum = N*(N+1) / 4;

    long long DP[800][40] = {0};
    DP[0][0] = 1;

    for (int idx1=1; idx1 <= N ; ++idx1)
        for (int idx2 = 0; idx2 <= sum ; ++idx2)     
            DP[idx2][idx1] = DP[idx2][idx1-1];
        for (int idx2 = 0; idx2 <= sum -idx1; ++idx2) 
            DP[idx2+idx][idx1] += DP[idx2][idx1-1];

	fout << DP[sum][N-1] << "\n";

 

Chapter 2. Bigger Challenges

'USACO Training' 카테고리의 다른 글

Problem 1.5.3 Mother's Milk  (0) 2019.10.12
Problem 2.3.4 Money Systems  (0) 2019.10.11
Problem 2.1.5 Sorting A Three-Valued Sequence  (0) 2019.09.18
Problem 2.1.4 Ordered Fractions  (0) 2019.09.18
Problem 2.2.5 Runaround Numbers  (0) 2019.09.18

+ Recent posts