メモ

yukicoderでゆるふわgolf

yukicoder No.561 東京と京都

問題はこちら
No.561 東京と京都 - yukicoder

DPやるだけ(といいつつ、後ろから見る方法しか思いつかなかったので要反省)

(i-1)日目が終了した時点で東京にいるときの最大利益をT、京都にいるときの最大利益をKとおく。
i日目に東京でt、京都でk得られる場合
i日目が終了した時点で東京にいるときの最大利益はmax(T,K-d)+t、京都にいるときの最大利益はmax(K,T-d)+kとなる。
これによりK,Tを順次更新していけば良い。
初期値はT=0、K=-dとなる。(1日目が始まる前に京都へ移動したと考える)

T,K,t,k,n,d;
main(){
	scanf("%d%d",&n,&d);
	K=-d;
	for(int i=0;i<n;i++){
		scanf("%d%d",&t,&k);
		t=fmax(T,K-d)+t;
		k=fmax(K,T-d)+k;
		T=t;
		K=k;
	}
	printf("%d",T>K?T:K);
}

数値は2個1セットで読み込めるので次のようにできる

T,K,t,k,d;
main(i){
	for(;~scanf("%d%d",&t,&k);){
		if(--i){
			t=fmax(T,K-d)+t;
			k=fmax(K,T-d)+k;
			T=t;
			K=k;
		}else{
			d=k;
			K=-d;
		}
	}
	printf("%d",T>K?T:K);
}

これをぎゅっとする

T,K,t,k,d;
main(i){
	for(;~scanf("%d%d",&t,&k);)K=--i?k+=fmax(K,T+d),T=t+fmax(T,K+d),k:(d=-k);
	printf("%d",T>K?T:K);
}

yukicoder No.537 ユーザーID

問題はこちら
No.537 ユーザーID - yukicoder

2つの数A,Bを連結するのは、文字列として処理するのでも良いが、Cだと面倒なので計算をする
数Bの桁数は\lfloor \log_{10} B \rfloor +1で得られるので、AとBをこの順で連結したものはA*10^{\lfloor \log_{10} B \rfloor +1}+Bで求められる

Nが大きいので1~√Nまでを調べる

long n,s[20000],k,i,t,A;
c(long*a,long*b){return *a<*b?1:*a>*b?-1:0;}
main(){
	scanf("%ld",&n);
	for(i=1;i*i<=n;i++)if(n%i==0){
		s[k++]=n/i*pow(10,t=log10(i)+1)+i;
		s[k++]=i*pow(10,t=log10(n/i)+1)+n/i;
	}
	qsort(s,k,8,c);
	for(;k--;)A+=s[k]!=s[k+1];
	printf("%d",A);
}

OEISによれば10^12以下の数は高々6720個の約数しか持たないので、「既出の数かどうか」は毎回チェックしても間に合う
また、iがnの約数なら、「iをn/iと取り替える」という操作を2度行うとiはもとの値に戻るので、これを利用して、前後の入れ替えを1つにまとめられる

long n,s[9999],k,i,j,t,x;
main(){
	scanf("%ld",&n);
	for(i=1;i*i<=n;i++)if(n%i==0){
		for(x=0;x<2;x++){
			t=n/i*pow(10,t=log10(i)+1)+i;
			for(j=0;j<k;j++)if(s[j]==t)break;
			if(j==k)s[k++]=t;
			i=n/i;
		}
	}
	printf("%d",k);
}

3重for文をいい感じにまとめる。
特に工夫せずとりあえず縮める

for(scanf("%ld",&n);i*i++<n;)
	for(;n%i?0:++x%3;j==k?s[k++]=t:0,i=n/i)
		for(t=n/i*pow(10,t=log10(i)+1)+i,j=0;j<k&&s[j++]-t;);

s[]への代入の部分もループの中にまとめたほうが短くなる

for(t=n/i*pow(10,t=log10(i)+1)+i,j=0;j<k?s[j++]-t:!(s[k++]=t););
for(t=n/i*pow(10,t=log10(i)+1)+i,j=k;j?s[--j]-t:!(s[k++]=t););

ということでできたのがこれ

long n,s[9999],i,x,k,t;
main(j){
	for(scanf("%ld",&n);i*i++<n;)
		for(;n%i?0:x++%3;i=n/i)
			for(t=n/i*pow(10,t=log10(i)+1)+i,j=k;j?s[--j]-t:!(s[k++]=t););
	printf("%d",k);
}

161B

yukicoder No.560 ふしぎなナップサック

問題はこちら
No.560 ふしぎなナップサック - yukicoder

算数やるだけ
ナップサックの中にM円入っているとき、1回叩いた後は (2M+(M+1)+0)*1/3=M+1/3 より(M+1/3)円になる。
これはMに依らないのでこの操作をN回行うとM+N/3円になる。
写像f(M)=M+1/3をN回適用した)

main(m,n){
	scanf("%d%d",&m,&n);
	printf("%.9f",m+n/3.);
}

53B

yukicoder No.559 swapAB列

問題はこちら
No.559 swapAB列 - yukicoder

求めるものは転倒数と同値
先頭から見ていってAが登場する度に、それ以前に登場したBの個数を数えれば良い

char s[99];
b,ans,n;
main(){
	gets(s);
	n=strlen(s);
	for(int i=0;i<n;i++){
		if(s[i]=='A')ans+=b;
		if(s[i]=='B')b++;
	}
	printf("%d",ans);
}

'A'は66、'B'は65なので、%2と%5でそれぞれ01にすることができる

b,s;
main(c){
	for(;read(0,&c,1);b+=c%5)s+=c%2*b;
	printf("%d",s);
}

62B

yukicoder No.558 575検出するやつ

問題はこちら
No.558 575検出するやつ - yukicoder

strstrするだけ

char s[110];
main(){
	gets(s);
	puts(strstr(s,"575")?"YES":"NO");
}

100文字をintに読み込んでも幸いREにはならず

a;main(){puts(strstr(gets(&a),"575")?"YES":"NO");}

50B
aをmain引数にするとRE