Codeforces Beta Round #40 (Div2)

参加はしてないですが、プラクティスで解いたので

A Translation

方針

回文になっているかどうか確かめる

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

int main() {
  string s,t;
  cin>>s>>t;
  reverse(s.begin(),s.end());
  if(s == t) cout<<"YES"<<endl;
  else cout<<"NO"<<endl;
}

B Martian Dollar

方針

明らかに2回以上取引することはないので、買う時と売る時の組み合わせを全部調べる

#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;

int main() {
  int n,b,j,c,d;
  vector<int> a;
  cin>>n>>b;
  for(int i=0; i<n; ++i) {
    cin>>j;
    a.push_back(j);
  }

  int maxd = b;
  for(int i=0; i<n; ++i) {
    for(int j=i+1; j<n; ++j) {
      if(a[j] > a[i]) {
	int dol = b / a[i];
	int rem = b % a[i];
	maxd = max(maxd, dol*a[j] + rem);
      }
    }
  }

  cout<<maxd<<endl;
}

C Email address

方針

規則にしたがって置き換える

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

int main() {
  string s;
  cin>>s;

  bool update = true;
  string next = string(1,s[0]);
  for(int i=1; i<s.length(); ++i) {
    if(i < s.length()-3 && s.substr(i,3) == "dot") {
      next += ".";
      i+=2;
    }else{
      next += string(1,s[i]);
    }
  }

  string nnext = string(1, next[0]);
  for(int i=1; i<next.length(); ++i) {
    if(i < next.length()-2 && next.substr(i,2) == "at") {
      nnext += "@";
      nnext += next.substr(i+2);
      break;
    }else{
      nnext += string(1,next[i]);
    }
  }

  cout<<nnext<<endl;
}

D Pawn

方針

位置とそこまでの和の(k+1)での余りの組み合わせでDPする

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

#define REP(i,a,b) for(i=a; i<b; ++i)
#define rep(i,n) REP(i,0,n)

int chess[101][101];
int dp[11][101][101];
char trace[11][101][101];

int main() {
  int n,m,i,j,k,l;
  string s,tans = "";
  cin>>n>>m>>k;
  k++;

  memset(trace, 0, sizeof(trace));
  memset(dp, -1, sizeof(dp));
  rep(i,n) {
    cin>>s;
    rep(j,m) chess[i][j] = s[j] - '0';
  }

  rep(j,m) dp[(chess[n-1][j])%k][n-1][j] = chess[n-1][j];

  for(int i=n-1; i>0; --i) rep(j,m) rep(l,k) {
	if(dp[l][i][j] != -1) {
	  if(j > 0) {
	    int ts = chess[i-1][j-1] + dp[l][i][j];
	    if(dp[ts%k][i-1][j-1] < ts) {
	      dp[ts%k][i-1][j-1] = ts;
	      trace[ts%k][i-1][j-1] = 'L';
	    }
	  }
	  if(j < m-1) {
	    int ts = chess[i-1][j+1] + dp[l][i][j];
	    if(dp[ts%k][i-1][j+1] < ts) {
	      dp[ts%k][i-1][j+1] = ts;
	      trace[ts%k][i-1][j+1] = 'R';
	    }
	  }
	}
      }

  int ans = -1, di = 0, dj = 0, dl = 0;
  rep(j,m) if(ans < dp[0][0][j]) ans = max(ans, dp[0][0][j]),dj = j;

  cout<<ans<<endl;

  char c;
  if(ans >= 0) {
    while((c = trace[dl][di][dj]) != 0) {
      tans += string(1, c);
      dl = (dp[dl][di][dj] - chess[di][dj])%k;
      (c == 'L') ? dj++ : dj--;
      di++;
      if(di == n-1) break;
    }
    reverse(tans.begin(), tans.end());
    cout<<dj+1<<endl;
    cout<<tans<<endl;
  }
}

E 3-cycles

方針

k個の端点のグラフに対して、端点の次数の小さい方から閉路ができないように貪欲に辺を追加する
求めたいグラフはどうやら2部グラフになる気がする(嘘かもしれない)

#include<iostream>
#include<cstring>
#include<vector>
#include<queue>
using namespace std;

#define REP(i,a,b) for(i=a; i<b; ++i)
#define rep(i,n) REP(i,0,n)

int used[100][100];
int deg[100];
int ans;

void add_edge(int p,int n) {
  int i,j;

  priority_queue<pair<int,int> ,vector<pair<int,int> >, greater<pair<int,int> > > Q;
  memset(deg, 0, sizeof(deg));
  rep(i,n) rep(j,n) if(used[i][j]) deg[i]++,deg[j]++;
  rep(i,p) Q.push(make_pair(deg[i],i));

  vector<pair<int,int> > pv;
  while(!Q.empty()) {
    pair<int,int> pi = Q.top(); Q.pop();
    bool isable = true;
    rep(j,p) if(used[j][pi.second] != 0 && used[p][j] != 0) isable = false;
    if(isable) used[p][pi.second] = used[pi.second][p] = 1,ans++;
  }
}

int main() {
  int n,i,j;
  ans = 0;
  cin>>n;
  memset(used, 0,sizeof(used));

  rep(i,n) add_edge(i,n);

  cout<<ans<<endl;
  rep(i,n) REP(j,i+1,n) if(used[i][j]) cout<<i+1<<" "<<j+1<<endl;
}