問題はこちら
No.601 Midpoint Erase - yukicoder
(x1,y1)と(x2,y2)の中点が格子点
⇔「(x1+x2)/2が整数」かつ「(y1+y2)/2が整数」
⇔「x1とx2の偶奇が等しい」かつ「y1とy2の偶奇が等しい」
よって与えられた点たちを、「x座標が偶数/奇数、y座標が偶数/奇数」という4つのグループに分けると、中点が格子点になるよう2点を選ぶことは、同じグループから2点を選ぶことと同値。
各グループに属する点の個数を数えて、全部で何組作れるかを見ればよい
a[2][2],n,x,y; main(){ scanf("%d",&n); while(n--){ scanf("%d%d",&x,&y); a[x%2][y%2]++; } if(a[0][0]/2+a[0][1]/2+a[1][0]/2+a[1][1]/2)%2==1)puts("Alice"); else puts("Bob"); }
作ることが出来る組の数(つまりa[0][0]/2+a[0][1]/2+a[1][0]/2+a[1][1]/2)をsとする。
sを最後に計算するのではなく、読み込みながら計算することを考える。
sが増えるのはa[*][*]が奇数から偶数に変化したときなので、s+=a[*][*]++%2とすることが出来る。
さらによく考えると、sは偶奇のみが必要なので、実は%2を省略してs+=a[*][*]としてよい。
また、配列は明らかに1次元4要素にまとめられる
s,x,a[4]; main(y){ for(gets(&y);~scanf("%d%d",&x,&y);)s+=a[x%2*2+y%2]++; puts(s%2?"Alice":"Bob"); }
95B
nの読み飛ばしを頑張るパターンも考えたが96Bにしかならず
s,x,y,a[4]; main(i){ for(;~scanf("%d",&y);x=y)s^=i--&!!i&&a[x%2*2+y%2]++%2; puts(s?"Alice":"Bob"); }