AtCoder Beginner Contest 053 by C
AtCoder Beginner Contest 053について
C言語での回答
最適な方針を思いつくのに時間がかかったり、
条件分岐に気付くのに時間がかかったりしてしまい、非常に悔しい思いをしました。
解説:https://img.atcoder.jp/arc068/editorial.pdf
できたもの
A
B
C
できなかったもの
D
問題A
#include <stdio.h> int main(void){ int x; scanf("%d", &x); if(x<1200){ printf("ABC"); } else{ printf("ARC"); } return 0; }
値が未満か以上で条件分岐
問題B
#include <stdio.h> #include <string.h> int main(void){ int i,j; char s[200001]; scanf("%s", s); int n = strlen(s); for(i=0;i<n;i++){ if(s[i]=='A'){ break; } } for(j=n-1;j>-1;j--){ if(s[j]=='Z'){ break; } } printf("%d", j-i+1); return 0; }
文字列で一番最初に出てくるAの位置と、最後に出てくるZの位置を求めればOK
文字数なので差に1を足してやる
こっちを思いついたのが後だったので時間かかっちゃって悔しい。
最初に思いついたのは先頭から文字をチェックし、AがあったらそこからZが出てくるまでの最長文字数を求めるというもの。
でもこれだと"BACZZXZ"みたいなZが連続した時や後ろにある時に、一番後ろではなく先頭のZを拾ってしまい、ダメでした。
int maxlen = 0; int countlen = 0; for(i=0;i<n;i++){ if(s[i]=='A'){ countlen++; for(j=i+1;j<n;j++){ if(s[j]=='Z'){ countlen++; break; } else{ countlen++; } } } if(maxlen<countlen){ maxlen = countlen; }
問題C
#include <stdio.h> int main(void){ long long x; int i; scanf("%lld", &x); long long count; if(x%11==0){ count = x/11 * 2; } else if(x%11>=1&&x%11<=6){ count = x/11 * 2 + 1; } else{ count = x/11 * 2 + 2; } printf("%lld", count); return 0; }
解けたんですが、すごく時間がかかってしまい悔しいところ。
最短で最大値をとるためにはサイコロの目は656565…と変化させれば良いので、値を11で割り、余りがなければ割った数×2(11は6と5を一回ずつだしたことを意味するので操作の回数は2倍です)
余りがある場合は、余りが1~6の場合と7~10の場合で+1回か+2回の分岐です。
6565...とすればよいこと、11で割ってなんやかんやすればよいとはすぐに気づきましたが、5656...と6565...で分岐するなとかいらんことを考えてました。そこじゃない。11で割ったあまりによって分岐の部分に気付くのが遅く、えらい時間をくったのです。
問題D
以下解説より
操作を言い換えると、「2枚のカードを選んで取り除く」ということ。
k種類のカードがあるとすると、
・kが偶数の時、被ってないカードも1枚なくなるのでk-1枚
・kが奇数の時はk枚
種類ごとにカウントする(class[])まわりを参考にして合格しました。
#include <stdio.h> int main(void){ int n,i,j; int a; int class[100001] = {0}; int max=0; scanf("%d", &n); for(i=0;i<n;i++){ scanf("%d", &a); class[a]++; } for(i=0;i<100001;i++){ if(class[i]>=1){ max++; } } if(max%2==0){; max = max-1; } printf("%d", max); return 0; }
↓テストケース一つだけ時間超過になったコード。
テストケースの中身を見たところn=99999でO(n!)の計算になってたので当然な気も。
#include <stdio.h> int main(void){ int n,i,j; int a[100001]; int class; int max; scanf("%d", &n); for(i=0;i<n;i++){ scanf("%d", &a[i]); } //被っている数字があったら0にする for(i=0;i<n;i++){ if(a[i]!=0){ for(j=i+1;j<n;j++){ //printf("%d番目は%d\n", i, a[i]); if(a[j]==a[i]){ a[j]=0; //printf("%dと同じ%d番目は%d\n", a[i],j, a[j]); } } } } //0でない個数を数える for(i=0;i<n;i++){ printf("%d\n", a[i]); if(a[i]!=0){ class++; } } //printf("%d\n", class); if(class%2!=0){ max = class; } else{ max = class-1; } printf("%d", max); return 0; }