Reprint please indicate the source, thank you http://blog.csdn.net/ACM_cxlove? Viewmode = contents by --- cxlove
The most basic principle is that n + 1 objects are placed in N boxes. At least one box contains two objects.
Poj 2356
Http://poj.org/problem? Id = 2356
There are n numbers, and the sum of several numbers is a multiple of N.
I have to say that mathematics is a magic thing. The conclusion is that the sum of N numbers is a multiple of N.
Next, let's give a simple demonstration of the introduction of the black books in the combined mathematical books. SK indicates A1 + A2 + ...... AK, if SK is a multiple of N, then directly take SK, otherwise the remainder of the S1-Sn except N is distributed in 1 --- (n-1) The n-1 number, using the Pigeon nest principle, there must be the same remainder, that is, (Si % n) = (SJ % N), that is, (SJ-Si) % n = 0.
/* ID: cxloveprob: poj 2356 data: 2012.4.6hint: Pigeon nest principle */# include <iostream> # include <cstdio> # include <cstring> using namespace STD; int main () {int N, K; int A [10005] = {0}, B [10005]; while (scanf ("% d", & N )! = EOF) {bool flag = false; memset (B, 0, sizeof (B); For (INT I = 1; I <= N; I ++) {scanf ("% d", & K); If (FLAG) continue; A [I] = A [I-1] + K; if (A [I] % N = 0) {printf ("% d \ n", I); For (Int J = 1; j <= I; j ++) printf ("% d \ n", a [J]-A [J-1]); flag = true ;} else if (B [A [I] % N]) {printf ("% d \ n", I-B [A [I] % N]); for (Int J = B [A [I] % N] + 1; j <= I; j ++) printf ("% d \ n ", A [J]-A [J-1]); flag = true;} elseb [A [I] % N] = I ;}} return 0 ;}
Poj 3370 http://poj.org/problem? Id = 3370
Similar to the above question, the sum of m from N is a multiple of C, because C <= N, using the above proof, the number of consecutive k numbers must be a multiple of C. Note that it may overflow.
/* ID: cxloveprob: poj 3370 data: 2012.4.6hint: Pigeon nest principle */# include <iostream> # include <cstdio> # include <cstring> # define ll long longusing namespace STD; ll a [100005] = {0}, B [100005]; int main () {int N, K, C; while (scanf ("% d ", & C, & N )! = EOF & N + C) {bool flag = false; memset (B, 0, sizeof (B); For (INT I = 1; I <= N; I ++) {scanf ("% d", & K); If (FLAG) continue; A [I] = A [I-1] + K; if (A [I] % C = 0) {for (Int J = 1; j <I; j ++) printf ("% d", J ); printf ("% d \ n", I); flag = true;} else if (B [A [I] % C]) {for (Int J = B [A [I] % C] + 1; j <I; j ++) printf ("% d", J ); printf ("% d \ n", I); flag = true;} elseb [A [I] % C] = I ;}} return 0 ;}
Poj 3145 http://poj.org/problem? Id = 3145
The previous question is the clever use of the Pigeon nest principle.
There are two types of operations
B x: place the mathematical x (1-500000) in the set,
A y: the smallest number of Modulo Y in the output set. If there are multiple elements, the elements that are finally put into the set are output.
Consider the following problem, in 0-(Y-1) in the modulo Y minimum number must be 0-(Y-1) in the smallest number of numbers, so forth (Y ~ 2 * Y-1) (2 * Y ~ 3 * Y-1 )......, The line segment tree inserts numbers and finds the smallest number in the interval.
/* ID: cxloveprob: Harmony forever data: 2012.2.24hint: Line Segment tree, pigeon nest principle */# include <iostream> # include <cstdio> # include <cstring> # define INF 1 <30 # define Max 500000 using namespace STD; struct line {int left, right, mid; int val;} l [Max * 4]; int POS [Max + 5], CNT, Val [Max + 5]; void bulid (INT step, int L, int R) {L [STEP]. left = L; L [STEP]. right = r; L [STEP]. mid = (L + r)/2; L [STEP]. val = inf; If (L = r) return; bulid (Step <1, L, (L + r)/2); bulid (Step <1 | 1, (L + r)/2 + 1, R);} void Update (INT step, int POS) {If (L [STEP]. left> POS | L [STEP]. right <POS) return; If (L [STEP]. left> = POS & L [STEP]. right <= POS) {L [STEP]. val = Pos; return;} If (Pos <= L [step]. mid) Update (Step <1, POS); elseupdate (Step <1 | 1, POS); L [STEP]. val = min (L [step <1]. val, L [step <1 | 1]. val);} int query (INT step, int L, int R) {If (L [STEP]. left> r | L [STEP]. right <L) return INF; If (L [STEP]. left> = L & R> = L [STEP]. right) return l [st EP]. val; If (L [STEP]. left <L [STEP]. right) return min (query (Step <1, L, R), query (Step <1 | 1, L, R); Return INF ;} void slove (INT mod) {int L = 0, r = mod-1, ANS =-1, temp, K; while (L <= max) {If (r> MAX) r = max; temp = query (1, L, R); If (temp! = Inf) {If (ANS =-1 | (TEMP % mod) <(ANS % mod) ans = temp; else if (TEMP % mod) ==( ans % mod) & Pos [temp]> POS [ANS]) ans = temp;} l + = MOD; R + = MOD ;} printf ("% d \ n", POS [ANS]);} void fun (INT mod) {int ans = inf, K; For (INT I = cnt-1; i> = 1; I --) {If (Val [I] % mod = 0) {k = I; break;} If (Val [I] % mod <ans) {ans = Val [I] % MOD; k = I ;}} printf ("% d \ n", k) ;}int main () {int Q, m, tt = 0; char STR [5]; while (scanf ("% d", & Q) {If (tt> 0) printf ("\ n"); printf ("case % d: \ n", ++ TT); bulid (1, 0, max); CNT = 1; for (INT I = 0; I <q; I ++) {scanf ("% s", STR); If (STR [0] = 'B ') {scanf ("% d", & M); Val [CNT] = m; POS [m] = CNT ++; update (1, m );} else {scanf ("% d", & M); If (CNT = 1) printf ("-1 \ n"); else if (M <= 5000) fun (m); else slove (m) ;}} return 0 ;}