メモ

yukicoderでゆるふわgolf

yukicoder No.632 穴埋め門松列

問題はこちら
No.632 穴埋め門松列 - yukicoder

ありえる入力は6通りしかないので全て手で確認してみよう
2,3,?→1
2,?,3→14
3,2,?→4
3,?,2→14
?,2,3→4
?,3,2→1
ということで、「真ん中がそれぞれ2,3,?のとき答えはそれぞれ4,1,14」となることがわかる

char s[9];
main(){
	gets(s);
	if(s[2]=='2')puts("4");
	if(s[2]=='3')puts("1");
	if(s[2]=='?')puts("14");
}

ゴルフの方針として、とりあえずこんなのをぱっと思いつく

main(s){gets(&s);s>>=16;write(1,"14"+(0or1),1or2);}

ぐっと睨むと次のような物を得る

main(s){gets(&s);s>>=16;write(1,"14"-~s%2,(s&24)/9);}

53B
getsではなくreadを使うことも考えたが、結局同じ長さにしかならなかった

main(s){read(0,&s,3);write(1,"14"-~s%2,(s>>=16)/31);}

yukicoder No.604 誕生日のお小遣い

問題はこちら
No.604 誕生日のお小遣い - yukicoder

算数するだけ。
A年間で(A-1+B)円もらえる。
残りの端数は、A-1以下なら1円ずつもらってる内に貯まり、それ以上ならA年目までかかる。
よって答えはC/(A+B-1)*A+min(A,C%(A+B-1))となる。

long a,b,c;
main(){
	scanf("%ld%ld%ld",&a,&b,&c);
	printf("%ld",c/(b+=a-1)*a+(a<c%b?a:c%b));
}

88B

yukicoder No.601 Midpoint Erase

問題はこちら
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");
}

yukicoder No.64 XORフィボナッチ数列

問題はこちら
No.64 XORフィボナッチ数列 - yukicoder

xorを表す記号を\oplusとする。
a\oplus b=b\oplus a\\
(a\oplus b)\oplus c=a\oplus(b\oplus c)\\
a \oplus b \oplus b =a
が成立する事に注意すると、
F_2=F_1\oplus F_0\\
F_3=F_2\oplus F_1=(F_1 \oplus F_0)\oplus F_1=F_0\\
F_4=F_3\oplus F_2=F_0\oplus(F_1 \oplus F_0)=F_1
となるから、結局
F_{n+3}=F_n
となることが分かる。つまり、nの3での剰余について場合分けすればよい。

long a,b,n;
main(){
	scanf("%ld%ld%ld",&a,&b,&n);
	if(n%3==0)printf("%ld",a);
	if(n%3==1)printf("%ld",b);
	if(n%3==2)printf("%ld",a^b);
	return 0;
}

n%3で0とそれ以外の区別はつくが、1と2の区別は~n%3でつけることができるので

long a,b,n;
main(){
	scanf("%ld%ld%ld",&a,&b,&n);
	n=!printf("%ld",n%3?~n%3?b:a^b:a);
}

81B