【AOJ 1610】Bamboo Blossoms
問題
Bamboo Blossoms | Aizu Online Judge
方針
- エラトステネスの篩的に消していく.
- Nが0になったときのiが答え.
コード
#include <iostream> #include <cmath> using namespace std; #define MAX 7368791 int main(){ int m, n; bool flag[MAX]; while(cin >> m >> n, m||n){ for(int i = 0 ; i <= MAX ; i++) flag[i] = false; for(int i = m ;; i++){ if(!flag[i]){ if(n == 0){ cout << i << endl; break; }else{ n--; for(int j = i ; j <= MAX ; j+=i){ flag[j] = true; } } } } } }
参考
【AOJ 2700】Airport Codes
問題
Airport Codes | Aizu Online Judge
方針
- 1文字目と母音の直後の文字を順に連結した文字列を作る.
- k文字未満ならその文字列, k文字以上なら取り出した文字列の先頭からk文字分をコードとする.
- kを1から50まですべて試す(試しても間に合う制約なので)
コード
#include <iostream> #include <vector> #include <map> using namespace std; #define rep(i, n) REP(i,0,n) #define REP(i,a,n) for(int i = a ; i < (int)n ; i++) string name[101]; bool isvowel(char c){ return (c == 'a' || c == 'i' || c == 'u' || c == 'e' || c == 'o'); } string getCode(string s, int k){ string ans; ans = s[0]; int len = s.size() - 1; REP(i, 0, len){ if(isvowel(s[i])){ ans += s[i+1]; } } if((int)ans.size() < k) return ans; return ans.substr(0, k); } int check(int n){ bool flag; REP(k, 1, 51){ flag = true; map<string, bool> mp; rep(i, n){ string s = getCode(name[i], k); if(mp.count(s) == 0){ mp[s] = true; }else{ flag = false; break; } } if(flag) return k; } return -1; } int main(){ int n; while(cin >> n, n){ rep(i, n){ cin >> name[i]; } int ret = check(n); cout << ret << endl; } }
【AOJ 2706】Let's Solve Geometric Problems
問題
Let's Solve Geometric Problems | Aizu Online Judge
方針
- b進数k桁の値は以下のように表すことができる.
- 上の式を変換すると,となることがわかる.
- 上記の式の形に変換したときのbが答え.
コード
#include <iostream> #include <cmath> #include <utility> #include <vector> #include <algorithm> using namespace std; typedef pair<int, int> pii; signed main(){ int p, q; int k; cin >> p >> q; k = __gcd(p, q); p /= k; q /= k; int q_ = q; vector<pii> ans; for(int i = 2 ; i <= sqrt(q) ; i++){ if(q_%i == 0){ pii p = make_pair(i, 1); q_ /= i; while(q_%i == 0){ p.second++; q_ /= i; } ans.push_back(p); } } if(q_ > 1) ans.push_back(pii(q_, 1)); int a = 1; for(int i = 0 ; i <(int) ans.size() ; i++){ a *= ans[i].first; } cout << a << endl; }
【AOJ ALDS1_7】B: Tree - Binary Trees
問題
Binary Trees | Aizu Online Judge
方針
- 二分木を作ろう.
コード
#include <iostream> using namespace std; struct Node{ int parent, left, right; }; int n; Node T[30]; int D[30], H[30]; void depth(int u, int d){ if(u == -1) return; D[u] = d; depth(T[u].left, d+1); depth(T[u].right, d+1); } int height(int u){ int ret1 = 0, ret2 = 0; if(T[u].left != -1) ret1 = height(T[u].left) + 1; if(T[u].right != -1) ret2 = height(T[u].right) + 1; return (H[u] = max(ret1, ret2)); } signed main(){ cin >> n; int u, l, r; for(int i = 0 ; i < 30 ; i++){ T[i].parent = T[i].left = T[i].right = -1; } for(int i = 0 ; i < n ; i++){ cin >> u >> l >> r; T[u].left = l; T[u].right = r; if(l != -1) T[l].parent = u; if(r != -1) T[r].parent = u; } int root; for(int i = 0 ; i < n ; i++){ if(T[i].parent == -1) root = i; } depth(root, 0); height(root); for(int i = 0 ; i < n ; i++){ cout << "node " << i << ": "; cout << "parent = " << T[i].parent << ", "; cout << "sibling = "; if(T[i].parent == -1){ cout << -1 << ", "; }else if(T[T[i].parent].left != -1 && T[T[i].parent].left != i){ cout << T[T[i].parent].left << ", "; }else if(T[T[i].parent].right != -1 && T[T[i].parent].right != i){ cout << T[T[i].parent].right << ", "; }else{ cout << -1 << ", "; } cout << "degree = " << (T[i].left!=-1?1:0)+(T[i].right!=-1?1:0) << ", "; cout << "depth = " << D[i] << ", "; cout << "height = " << H[i] << ", "; if(root == i) cout << "root" << endl; else if(T[i].left != -1 || T[i].right != -1) cout << "internal node" << endl; else cout << "leaf" << endl; } }
【AOJ 2331】A Way to Invite Friends
問題
A Way to Invite Friends | Aizu Online Judge
方針1
- 配列の[a, b]を++していく. 配列fをf[i]:=i人誘う時行くことができる友達の数とする.
- i-1(自分を抜いた数)誘うときに, i - 1 <= f[i]となればi-1人誘えるということになる.
方針2
- aのときにf[a]を1増やし, bのときf[b]を1減らす.
- iを2から増やしつつ配列の値の総和を出し, i以上になったとき誘える人数.
コード(方針1)
#include <iostream> using namespace std; #define rep(i,n) REP(i,0,n) #define REP(i,a,n) for(int i = a ; i < (int)n ; i++) int f[100005]; signed main(){ int n; int a, b; cin >> n; rep(i, n){ cin >> a >> b; REP(j,a,(b+1)){ f[j]++; } } int idx = 0; REP(i, 2, 100002){ if(i-1 <= f[i]){ idx = i-1; } } cout << idx << endl; }
コード(方針2)
#include <iostream> using namespace std; #define rep(i,n) REP(i,0,n) #define REP(i,a,n) for(int i = a ; i < (int)n ; i++) int f[100005]; signed main(){ int n; int a, b; cin >> n; rep(i, n){ cin >> a >> b; f[a]++; f[b + 1]--; } int sum = 1; int idx = 0; rep(i, 100002){ // i人誘う sum += f[i]; if(i <= sum){ // n人中sum人が行くことができる. i<=sumを満たしてればよい idx = i; } } idx--; cout << idx << endl; }
2の方, なんかimosっぽいなぁと思いました. コミュ力を上げて友達を増やそう.
【AOJ 1193】Chain Disappearance Puzzle
問題
方針
- 横に3つ以上連鎖している箇所は消すことができる.
- 消えた部分には, 上にある石が空きを埋めるように落ちてくる.
- すべての石を落とした後に消滅の条件をみたすようなものがあればまた繰り返す.
上の通りにシミュレーションする.
コード
#include <iostream> #include <algorithm> using namespace std; #define REP(i,a,n) for(int i = a ; i < (int)n ; i++) #define rep(i,n) REP(i,0,n) int h; int field[20][10]; signed main(){ while(cin >> h, h){ rep(i, h){ rep(j, 5){ cin >> field[i][j]; } } int ans = 0; bool flag = true; while(flag){ int tmp = 0; rep(i, h){ int prev = -1; int count = 0; int start = 0; REP(j, 0, 5){ if(prev == field[i][j] && field[i][j] > 0){ count++; if(count >= 3 && field[i][j+1]!=field[i][j]){ REP(k, 0, count){ tmp += field[i][start+k]; field[i][start+k] = -1; } count = 1; } }else{ if(count >= 3){ REP(k, 0, count){ tmp += field[i][start+k]; field[i][start+k] = -1; } } start = j; count = 1; prev = field[i][j]; } } } if(tmp == 0){ cout << ans << endl; flag = false; continue; } ans += tmp; REP(k, 1, h){ rep(l, 5){ if(field[k][l] == -1 && field[k-1][l]){ for(int m = k ; m > 0 ; m--){ swap(field[m][l], field[m-1][l]); } } } } } } }
【AOJ ALDS1_5】D: Recursion / Divide and Conquer - The Number of Inversions
問題
反転数 | アルゴリズムとデータ構造 | Aizu Online Judge
方針
- 反転数を求める問題.
- バブルソートの要領で探すとになってTLEするので効率よく探す必要がある.
- タイトルの通り, 分割統治法(マージソート)を活用することででカウントすることができる.
- 反転数は, 対象データが格納されている配列を二分しLとRを作った時, 配列Rの各要素R[j]について, R[j]よりもあとに移動するようなLの要素は, (Lの要素数)-(Lの現在のインデックス)で求められる.
コード
#include <iostream> using namespace std; typedef long long ll; #define rep(i,n) REP(i,0,n) #define REP(i,a,n) for(int i = a ; i < (int)n ; i++) #define INF 2000000000 #define int ll ll n; ll input[200001]; ll l[100002]; ll r[100002]; ll merge(int left, int right, int mid){ rep(i, mid - left) l[i] = input[left + i]; rep(i, right - mid) r[i] = input[mid + i]; // 番兵 l[mid -left] = r[right - mid] = INF; int l_idx, r_idx; ll cnt; l_idx = r_idx = 0; cnt = 0; REP(i, left, right){ if(l[l_idx] <= r[r_idx]){ input[i] = l[l_idx]; l_idx++; }else{ input[i] = r[r_idx]; r_idx++; cnt += ((mid - left) - l_idx); } } return cnt; } ll mergeSort(int left, int right){ if(right - left > 1){ int mid = (right + left)/2; ll ret = mergeSort(left, mid); ret += mergeSort(mid, right); return (ret + merge(left, right, mid)); }else{ return 0; } } signed main(){ cin.tie(0); ios::sync_with_stdio(false); cin >> n; rep(i, n){ cin >> input[i]; } cout << mergeSort(0, n) << endl; }
参考
www.slideshare.net