見出し画像

ABC185 参戦記録 p.33

itsukiです。
AtCoder Beginner Contest 185 に参戦した様子です。解説記事ではありません。

結果は A, B, C の 3完でした。
回答時間合計:70分25秒
パフォーマンス:536

考察の流れ

A - ABC Preparation

A1, A2, A3, A4 の最小値!
#include <stdio.h>
#define MIN(x,y)	((x)<(y)?(x):(y))
int main(){
   int a1,a2,a3,a4,ans;
   scanf("%d%d%d%d",&a1,&a2,&a3,&a4);
   ans = MIN(a1,a2);
   ans = MIN(ans,a3);
   ans = MIN(ans,a4);
   printf("%d\n",ans);
   return 0;
}

ここまで:1分46秒

B - Smartphone Addiction

問題文を理解するまでに時間がかかる
(当初の方針)
「カフェに寄らない場合(N - T)」に
「カフェに寄った時間(B_i - A_i)の 2倍」の和を足していけばいい?
-> フル充電になった場合や、途中で 0になった場合が抜けていてダメ!
問題文の流れをそのまま愚直に書く
#include <stdio.h>
#define Yes()       printf("Yes\n")
#define No()        printf("No\n")
typedef long long ll;
int main(){
   ll n,m,t,a[1005]={0},b[1005]={0},tmp,now=0;
   scanf("%lld%lld%lld",&n,&m,&t);
   tmp=n;
   for(int i=0; i<m; i++){
       scanf("%lld%lld",&a[i],&b[i]);

       // 消費
       tmp -= (a[i]-now);
       if( tmp <= 0 ){ No(); return 0; }
       now = a[i];

       // 充電
       tmp += (b[i]-now);
       if( tmp > n ){ tmp = n; }   // フル充電
       now = b[i];
   }
   // 最後のカフェ~帰宅
   tmp -= (t-now);

   if( tmp <= 0 ){ No();  }
   else          { Yes(); } 
   return 0;
}

ここまで:31分16秒
・最初の方針がダメだったときに、立て直すまでに時間をかけすぎ
・サンプルが親切だったから助かったようなもの…

C - Duodecim Ferra

組み合わせか?と思いつつ ggって迷走し、「全射の個数」「スターリング数」にまで漂流
順列/組み合わせを履修した時に「仕切りを入れる場所の選び方」を考えたのを思い出す
「仕切りをいれることが出来る場所の数」を n 、「仕切りの数」を r とする nCr を考えると
 n = L-1
 r = 12-1
という組み合わせの問題になる
#include <stdio.h>
typedef long long ll;
ll _nCr(ll n, ll r){ if( n<r || n<0 || r<0 ){ return 0; } ll ans=1; if(r>(n-r)){ r=n-r; } for(ll i=1;i<=r;i++){ ans*=(n+1-i); ans/=i; } return ans; }
int main(){
   ll i,n,k=12,ans=0;
   scanf("%lld",&n);
   printf("%lld\n",_nCr(n-1,k-1));
   return 0;
}

ここまで:70分25秒
・迷走した時間がもったいなかった
・解説を見たところ、オーバーフローの危険があったらしい…自作の nCr 関数は大丈夫だったぽいが、全く考えていなかったのでもしこれでオーバーフローだったらアウトだった

D - Stamp

入力例 4 より、M==0 の場合は ハンコの大きさ (k) = 全マス (N) になるため、答えは 0
一番幅の狭いところが k になる(ここでコンテスト終了)

コンテスト後:

先頭マスが青色(A_1==1)だったり、末尾マスが青色(A_M==N)だったりした場合に 場合分けが面倒なので、N個のマスの両端に青色マスを置く
下図は入力例 1 の脳内イメージ

画像1

あとはひたすら 連続する白色マスの数を、ハンコの大きさ k で割って小数点以下を切り上げたものを加算していく
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define MIN(x,y)	((x)<(y)?(x):(y))

int compare_int(const void *a, const void *b){
   return *(int*)a - *(int*)b;
}

int main(){
   int i,n,m,a[200005]={0},k=999999999,tmp,ans=0;
   scanf("%d%d",&n,&m); n++;

   // 全部白
   if(m==0){ printf("1\n"); return 0; }

   a[0]=0; a[m+1]=n+1;
   for(i=0; i<m; i++){ scanf("%d",&a[i+1]); }
   qsort( a, m+1, sizeof(int), compare_int );

   for(i=0; i<=m; i++){
       tmp = MIN(k, a[i+1]-a[i]);
       if( tmp!=1 ){ k=tmp; }
   }

   // 全部青
   if( k==1 ){ printf("0\n"); return 0; }
   k--;

   for(i=0; i<=m; i++){
       ans += (int)ceil((double)(a[i+1]-a[i]-1) / (double)k);
   }
   printf("%d\n",ans);
   return 0;
}

まとめ

・「問題文通り書く」があまりにも苦手
・順列/組み合わせの履修結果を発揮できたのは嬉しい
・発想は良くても、早解きできないと(コンテストでは)意味がない
・このまま 1色上のパフォーマンスを安定して積み上げていきたい

引き続き、のんびり精進します。

#参戦記録 #備忘録 #AtCoder #ABC #プログラミング #競プロ #C言語 #組み合わせ #数学

この記事が気に入ったらサポートをしてみませんか?