メモ

yukicoderでゆるふわgolf

yukicoder No.547 未知の言語

問題はこちら
No.547 未知の言語 - yukicoder

scanfを使うと空白区切りで読み込めるのでstrcmpで比較するだけ

char s[11][22];
char t[11][22];
main(){
	int n;
	scanf("%d",&n);
	for(int i=0;i<n;i++)scanf("%s",s[i]);
	for(int i=0;i<n;i++)scanf("%s",t[i]);
	for(int i=0;i<n;i++)if(strcmp(s[i],t[i]))printf("%d\n%s\n%s",i+1,s[i],t[i]);
}


まとめて1つの配列に読み込めばループも1つにできる
配列はchar型でなくても構わない
Nの読み込みなどに注意してざっくりまとめるとこうなる

s[25][6],n,i;
main(){
	for(;~scanf("%s",s[n]);n++);//nのincを中に入れるとn/2が1大きくなってしまう
	for(;!strcmp(s[i],s[++i+n/2]););
	printf("%d\n%s\n%s",i,s[i],s[i+n/2]);
}

for文を1つにまとめる

s[25][6],n,i;
main(){
	for(;~scanf("%s",s[n])?++n:!strcmp(s[i],s[++i+n/2]););
	printf("%d\n%s\n%s",i,s[i],s[i+n/2]);
}

112B

yukicoder No.533 Mysterious Stairs

問題はこちら
No.533 Mysterious Stairs - yukicoder

初期値にちょっと気をつける必要があるがDPやるだけ。
dp[昇った段数合計][直前に段数]=場合の数

dp[1000010][4];n;
mod=1000000007;
main(){
	dp[1][1]=1;
	dp[2][2]=1;
	dp[3][1]=dp[3][2]=dp[3][3]=1;
	scanf("%d",&n);
	for(int i=4;i<=n;i++){
		dp[i][1]=(dp[i-1][2]+dp[i-1][3])%mod;
		dp[i][2]=(dp[i-2][1]+dp[i-2][3])%mod;
		dp[i][3]=(dp[i-3][1]+dp[i-3][2])%mod;
	}
	printf("%d",(dp[n][1]+dp[n][2]+dp[n][3])%mod);
}

実際には3段前までの情報があればいいので、直前の9状態から次の3状態を生成するDP。
ということは何かいい感じの漸化式ができるのでは……と思いながらOEISを見たらビンゴ
A155822 - OEIS
次の2つの漸化式が書いてあった

a_n = a_{n-1} - a_{n-2} + 2*a_{n-3} - a_{n-4} + 2*a_{n-5} \ \ (n>5)\\
a_n = a_{n-3} + a_{n-4} + a_{n-5} + 2*a_{n-6} \ \ (n>6)
引き算が入っているとmodをとる時にこまるのと、単純に式が短い方が嬉しいので後者を採用した
代入が多いのでmain再帰で書いたけど、初期値を与えるもっと簡単な方法はないのだろうか……

n;M=1e9+7;main(a,b,c,d,e,f){~scanf("%d",&n)?main(1,1,3,3,4,8):--n?main(b,c,d,e,f,(0L+d+c+b+a+a)%M):printf("%d",a);}

115B


2017/07/29追記
自明な2B

n;M=1e9+7;main(a,b,c,d,e,f){~scanf("%d",&n)?main(1,1,3,3,4,8):--n?main(b,c,d,e,f,(2L*a+b+c+d)%M):printf("%d",a);}

113B

yukicoder No.538 N.G.S.

問題はこちら
No.538 N.G.S. - yukicoder

数学するだけ

連立方程式
b_2=rb_1+d\\b_3=rb_2+d
を解き
r=\frac{b_3-b_2}{b_2-b_1},\ d=\frac{b_2^2-b_1 b_3}{b_2-b_1}
を得る。求める答えはrb_3+dであるからこれに代入して
\frac{b_3^2-b_2 b_3+b_2^2-b_1 b_3}{b_2-b_1}
となる。
b_iは最大10^5なので2乗すると32bitの範囲に収まらないことに注意する

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

式をぐっと睨むと(c*c+b*b-b*c-a*c)/(b-a)をc+(b-c)*(b-c)/(b-a)と書き換えられることがわかる(自力では気づけず)

long b,c;
main(a){
	scanf("%d%ld%ld",&a,&b,&c);
	printf("%ld",c+(b-c)*(b-c)/(b-a));
}

79B

yukicoder No.544 Delete 7

問題はこちら
No.544 Delete 7 - yukicoder

Cで文字列処理をするのはつらいので数値として扱う。
下の位から順に見ていって、7であるようなところは6と1に分解する。それ以外はそのまま。
例えば72727なら62626+10101にする

int s,n,i;
main(){
	scanf("%d",&n);
	for(i=1;i<n;i*=10)if(n/i%10==7)s+=i;
	printf("%d %d",n-s,s);
}

もうほとんど縮めるところもないけれど、ぎゅっとして

s,n;
main(i){
	for(scanf("%d",&n);n/i;i*=10)s+=n/i%10-7?0:i;
	printf("%d %d",n-s,s);
}

80B

yukicoder No.543 命題

問題はこちら
No.543 命題 - yukicoder

問題文をよく読むと、入力「a b」に対しては「b a」を出力すれば良いことがわかる

main(){
	char a,b;
	scanf("%c %c",&a,&b);
	printf("%c %c",b,a);
}

1行まるごとひっくり返せばよい
頭から読んでお尻から出力→main再帰

main(i){read(0,&i,1);i&8||main()+putchar(i);}

45B


2017/08/13追記
普通にやったほうが短かった

main(i){gets(&i);printf("%c %c",i>>16,i);}

42B

数値のまま文字列処理するのも考えたけど流石にそれは長かった

main(i){gets(&i);i=i%255*65537-2080800-i;puts(&i);}
main(i){gets(&i);i+=(i%65537-8192)*65535;puts(&i);}