問題はこちら
No.141 魔法少女コバ - yukicoder
逆から考える
a/b<1を作るためには最後の操作は逆数を取るしかない
a/b>1を作るための最後の操作が逆数を取るものだとしたら上のパターンに戻るだけなのでだめで、結局+1しかない
前者の操作をの直後には必ず後者の操作が行われ、後者の操作ではa+bの値は真に小さくなっていくので、これらの操作によりa/bはいずれ1になる
つまり任意のM/Nを作ることができる
ということでこれを愚直に実装すれば間に合う
int main(){ int s=0,a,b,t; scanf("%d%d",&a,&b); while(a!=b){ if(a<b){t=a;a=b;b=t;} else a-=b; s++; } printf("%d",s); return 0; }
while文の中で、a>bの時は結局a<=bになるまで減算が行われるので、その回数を除算で求めることで複数回をまとめることができる
また、終了条件が面倒なのでちょっといじる
s,a,b;
main(t){
scanf("%d%d",&a,&b);
while(b){
s+=a/b+1;
t=a%b;a=b;b=t;
//a<bになるまで(1)を使い、その後は必ず(2)を使うのでa/b+1回
}
s=!printf("%d",s-2);
}
これにより本来は(a,b)=(1,1)で終わるところが、(1,1)→(0,1)→(1,0)と余分な操作を2回しているので出力時に引く
この方針で縮めると
s,a,b;
main(t){
for(scanf("%d%d",&a,&t);b=t;a=b)s+=a/b+1,t=a%b;
s=!printf("%d",s-2);
}
82B
やってることは互除法なんだから、main再帰でも書けるのでは
そうすれば、scanfも1つにまとめられる?
s;
main(a,b){
scanf("%d",&b);
s=b?s+=a/b+1,main(b,a%b):!printf("%d",s-3);
//入力時に(1,M)→(M,N)でsが+1されるので、上の2と合わせて計-3
}
サンプルは通るよしよし……と思ったら、M=1の時には最初の(1,M)→(M,N)で+2されてしまうので1ずれる
これは2Byte増やして解決
s;
main(a,b){
scanf("%d",&b);
s=b?s+=~-a/b+1,main(b,a%b):!printf("%d",s-2);
}
~-a/bは、a/b-!(a%b)に等しい(a,b>0のとき)
これにより、先程問題になっていた最初の部分はかならず+1に抑える事ができる
また最後にsに加算される値が1減るので、また出力が1ずれて-2となった
73B