import java.util.*; import java.util.regex.*; import static java.lang.Math.*; import static java.util.Collections.*; class Party { Set nominee = new LinkedHashSet(); // 候補者名簿 (input) int vote; // 得票数 (input) int s_seated; // 小選挙区での当選者数 (calculated) int hv; // 議席配分(小数) (calculated) : ただし整数演算にしたいので、得票数合計を掛けた値 int seats; // 議席配分(実際の値) (calculated) } class Nominee { String name; // 名前 (input) Party party; // 所属政党 (input) int vote; // 得票数 (input) } class EOI extends Exception {} class Election { public static void main( String[] args ) { try { int nCases=0; for(Scanner in = new Scanner(System.in) ;; ) { new Election(in).solve(); // The number of data sets in the input does not exceed fifty. ++nCases; assert nCases<=50; } } catch ( EOI e ) {} } final int SEAT; // 議席定数 final Map PARTY = new HashMap(); // 政党リスト final List> SHOS = new ArrayList>(); // 小選挙区リスト // read the input ------------------------------------------------------- Election( Scanner in ) throws EOI { Map personToParty = new HashMap(); Set personAppearedInSingle = new HashSet(); Set partyNames = new HashSet(); Set candiNames = new HashSet(); SEAT = in.nextInt(); int nPARTY = in.nextInt(); if( SEAT==0 && nPARTY==0 ) throw new EOI(); // The number of parties, the number of seats ... do not exceed 20, 200 ... assert 0 pvoteset = new HashSet(); // for assertion for(int i=0; i nvoteset = new HashSet(); // for assertion List sd = new ArrayList(); int anom = in.nextInt(); for(int j=0; j e = doElection(); // 辞書順に表示 sort(e); for( String s : e ) System.out.println(s); } List doElection() { List e = new ArrayList(); doShosenkyoku(e); // 小選挙区の当選者を計算 doHireiku(e); // 比例区の当選者を計算 return e; } void doShosenkyoku( List e ) { for( List sd : SHOS ) { // 得票数最大の人を Nominee w = max(sd, new Comparator(){ public int compare(Nominee lhs, Nominee rhs) { return lhs.voterhs.vote ? +1 : 0; }}); // 当選者リストに追加 e.add( w.name ); // 所属政党の小選挙区獲得議席を1増やす w.party.s_seated ++; // 所属政党の比例区の名簿から外す w.party.nominee.remove(w.name); } } void doHireiku( List e ) { // 比例区で議席をもらえる政党のリストを作成 // 政党.select {比例区得票数>=5% || 小選挙区当選者数>=3} List hParties = new ArrayList(); final int hsum_vote; { int sum_vote = 0; for( Party p : PARTY.values() ) sum_vote += p.vote; int hh = 0; for( Party p : PARTY.values() ) if( p.vote >= sum_vote/20 || p.s_seated >= 3 ) { hParties.add(p); hh += p.vote; } hsum_vote = hh; } // 議席配分 { int amari = SEAT; for( Party p : hParties ) { // 比例区得票数×議席定数÷全"対象"政党の得票数の合計 p.hv = p.vote * SEAT; // * 1.0 / hsum_vote; // の整数部分 p.seats = p.hv / hsum_vote; // 余り amari -= p.seats; } // (小数部(hv),得票数) の多い順にソート sort( hParties, new Comparator(){ public int compare( Party lhs, Party rhs ) { if( lhs.hv%hsum_vote < rhs.hv%hsum_vote ) return +1; if( lhs.hv%hsum_vote > rhs.hv%hsum_vote ) return -1; return lhs.voterhs.vote ? -1 : 0; }}); // 余りは上から順に1議席ずつわりあて for( Party p : hParties.subList(0, amari) ) p.seats ++; } // 比例区の当選者決定 (名簿の上から順にとってくるだけ) for( Party p : hParties ) { e.addAll( list(enumeration(p.nominee)).subList(0, max(0, p.seats-p.s_seated)) ); // Each party list contains enough candidates, that is, the party can always // choose the required number of candidates from the list. assert p.seats-p.s_seated <= p.nominee.size(); } } }