LoginSignup
2
0

More than 5 years have passed since last update.

ABCノート [ABC091~100]

Last updated at Posted at 2018-05-07

はじめに

このあいだの土曜日にABC初参加しました。ので、今後リアルタイムで参加したABCのノートを随時こちらにまとめていきます。ある程度溜まったところで新しい記事に移ります。[リアルタイムか否かよりも普通にナンバリングに沿ってノート作った方がわかりやすそうなのでタイトル変更しました。] 別解は僕の解答ではなく、解説だったり他の方の解答だったりします。アドバイス等大歓迎です。

096

解説

B – Maximum Sum

別解

#include <iostream>  
#include <algorithm>  
int A, B, C, K;  
int main() {  
  std::cin >> A >> B >> C >> K; std::cout << A + B + C + std::max({ A, B, C }) * ((1 << K) - 1) << '\n';  
  return 0;  
} 

std::max({a, b, c})

こんなのあったのか…

左シフト演算子 <<

左シフト演算子では、shift-expression のビットを、additive-expression で指定されたビット数だけ左にシフトします。 シフト演算により空いたビット位置はゼロで埋められます。 左シフトは論理シフトです (符号ビットを含めてシフトし、溢れたビットは捨てます)。

https://msdn.microsoft.com/ja-jp/library/336xbhcz.aspx#Anchor_0

C – Grid Repainting 2

解答

#include <iostream>  
#include <string>  
using namespace std;  

int h,w;  

int main() {  

cin >> h >> w;  
string s[h];  
for (int i = 0; i < h; i++) cin >> s[i];  

bool ok = false;  
for (int i = 0; i < h; i++) {  
  for (int j = 0; j < w; j++){  
    ok = false;  
    if(s[i][j] == '#') {  
      if((i > 0 && s[i-1][j] == '#') or 
         (i < h-1 && s[i+1][j] == '#') or 
         (j > 0 && s[i][j-1] == '#') or 
         (j < w-1 && s[i][j+1] == '#')) 
           ok = true;  

      if (!ok) { 
        cout << "No"; exit(0); 
      }  
    }  
  } 
} 
  cout << "Yes"; 
} 

別解

#include <iostream>  
using namespace std;  

char c[55][55]; int H, W, cnt;  

int main() {  

  cin >> H >> W;  
  for (int i = 1; i <= H; i++) {         
    for (int j = 1; j <= W; j++)  
      cin >> c[i][j];  
  }  

  for (int i = 1; i <= H; i++) {         
    for (int j = 1; j <= W; j++) {  
      if (c[i][j] == '#' && c[i][j - 1] != '#' && c[i - 1][j] != '#' && c[i][j + 1] != '#' && c[i + 1][j] != '#')  
        cnt++;  
    } 
  }  

if (cnt == 0) cout << "Yes" << endl;  
else cout << "No" << endl;  

return 0;  
} 

最後にcntで判定する方法は覚えておきたい。

D – Five, Five Everywhere

解答

選んだ5個の和が合成数かどうかの確認で躓いた。

#include <iostream>

using namespace std;

bool isPrime(int n){
  for(i = 2; i <= n / 2; ++i){
      if(n % i == 0){
          return false;
      }
  }
  return true;
}

int N;
int main() {
  cin >> N;
  int a[N];
  for(int i = 0; i < N; i++) {
    for(int n = i > 0 ? 2 : a[i-1]; n <= 55555; n++){
      if(isPrime(n)) a[i] = n;
      if(i > 4){
        for(int j = 4; j <= i; j++)
      }
    }
  }
}

別解

割れる、割れないの話なんだからmod忘れないようにしないと。

#include <iostream>
using namespace std;

bool isprime(int p) {
    if (p == 1) return false;
    for (int i = 2; i < p; i++) {
        if (p%i == 0) return false;
    }
    return true;
}

int n;

int main() {
    cin >> n;
    for (int i = 31; i <= 55555; i += 30) {
        if (isprime(i) == true) {
            if (i != 31) cout << " ";
            cout << i; n--;
        }
        if (n == 0) break;
    }
    cout << endl;
    return 0;
}

試しに
for (int i = 11; i <= 55555; i += 5)
で提出したら通った。31スタートでも変わらないのは良いとして、なぜ i+=30 だったんだろう。そっちの方が素数早く揃うのかな。

095

C - Half and Half

自分の解答

#include <iostream>
using namespace std;

int a, b , c , x ,y;

int main() {
  cin >> a >> b >> c >> x >> y;
  int total = 0;
  if (a + b > c * 2) {
    if (x > y) {
      if (a > c * 2) {
        total = c * x * 2;
      }
      else {
        total = c * y * 2+ a * (x - y);
      }
    } else {
      if ( b > c * 2) {
        total = c * y * 2;
      } else {
        total = c * x * 2+ b * (y - x);
      }
    }
  } else {
   total = a * x + b * y; 
  }
  cout << total;
}

別解

Taka0310さんより。上のifたちをまとめるとこうなるのか、、
A,B,Cの値段によって買い方のパターンが3つあってそれらのうち最も安くすむ値段を出力する。

(AとBをそれぞれx、y枚ずつ買った値段) v.s. (Cを2*max(x,y)枚買った値段)
v.s.
Cをmin(x,y)*2枚 + AあるいはBでより注文が多い方をCで足りない分買った値段

#include <iostream>
using namespace std;
int a, b, c, x, y, r;
int main() {
  cin >> a >> b >> c >> x >> y;
  cout << min(min(a*x+b*y, c*2*max(x,y)), min(x,y)*2*c+abs(x-y)*(x>y?a:b));
  return 0;
}

D - Static Sushi

自分の解答

初見でむりだったので解答のやり方で実装しようと3時間粘ってようやく解けたと思ったら公開テストケースの中で4つ目のみWAになって心が折れた。諦めて他の方の解答見て虚無感に包まれた。。つらい。。。

#include <iostream>
#include <vector>
#include <numeric>
using namespace std;
#define ll long long

ll N, C;
vector<ll> xs(1,0), vs(1,0); // reserve the first element for the start pos

int main() {
  cin >> N >> C;
  ll x, v;
  vector<ll> f(1,0) ,g(1,0);
  while (cin>>x){
    xs.push_back(x);
    cin >> v;
    vs.push_back(v);
    f.push_back(accumulate(vs.begin(), vs.end(),0) - x);
    if(g.size()>0) g.push_back(max(g.back(),f.back()));
    else g.push_back(f[0]);
  }
  ll ans = g.back(); // when B = O
  for(int b = N; b > 0; b--){
    ll sub = accumulate(vs.rbegin(), vs.rbegin()+N-b+1,0) - 2*(C-xs[b]); // -2OB
    ans = max(ans, g[b-1] + sub);
  } 

  g = f = vector<ll>(N+2,0);
  for(int b = 0; b < N; b++) {
    f[N-b] = accumulate(vs.rbegin(), vs.rbegin()+b+1,0);
    g[N-b] = max(g[N-b+1], f[N-b]-C+xs[N-b]);
  }
  ll anscw = g[1]; // when A = O
  for(int a = 1; a < N+1; a++){
    ll subcw = accumulate(vs.begin(), vs.begin()+a+1,0) - 2*xs[a]; // -2OA
    anscw = max(anscw, g[a+1] + subcw);
  } 

  cout << max(ans,anscw) << endl;
}

別解

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=100010;
int n;
long long c,mx,x[maxn],v[maxn],a[maxn],b[maxn];
int main()
{
    cin>>n>>c;
    for(int i=1;i<=n;i++)
    {
        cin>>x[i]>>v[i];
        a[i]=a[i-1]+x[i-1]-x[i]+v[i];
    }
    x[n+1]=c;
    for(ll i=n;i>=1;i--)b[i]=b[i+1]+x[i]-x[i+1]+v[i];
    for(int i=2;i<=n;i++)a[i]=max(a[i],a[i-1]);
    for(int i=n-1;i>=1;i--)b[i]=max(b[i],b[i+1]);
    for(int i=1;i<=n;i++)
    {
        mx=max(mx,a[i]),mx=max(mx,b[i]);
        mx=max(mx,a[i]-x[i]+b[i+1]);
        mx=max(mx,b[i]-(c-x[i])+a[i-1]);
    }
    printf("%lld\n",mx);
    return 0;
}
2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0