SRM677 Round1 Div.2
一応SRMは今年の3月に始めたのですが、基本的に深夜に行われていたり、学校にいる最中に行われていて中々参加が難しかったのですが、冬休みになって深夜の参加に挑戦してみました。
Easy PalindromePrime
問題概要
A positive integer is called a prime if it has exactly two distinct positive integer divisors: 1 and itself. The first few primes are 2, 3, 5, 7, 11, 13, ... A positive integer is called a palindrome if its base-10 representation reads the same forwards and backwards. Some palindromes: 2, 77, 101, 33333, 12344321. A positive integer is called a palindromic prime if it is both a palindrome and a prime. You are given two ints: L and R. Compute and return the number of palindromic primes between L and R, inclusive.
解法
L,R≦1000なので特に難しくないですね。素直に篩でRまでの素数を列挙して、出てきた素数の中でL~Rのものを抽出して、あとはそれが回文数かどうか判別するだけです。
他の人のコード見ると、stringに変換して両端から1文字ずつ確認しているところが殆どだったのですが、たかが4桁なのでそんな判定時間は気にしない。C++に甘えて、stringに変換したらreverse、同じ文字列か==で判定して終了、という方針をとりました。
#include <bits/stdc++.h> using namespace std; class PalindromePrime{ public: int count(int l,int r){ bool prime[r+1]; for(int i=0;i<=r;i++) prime[i]=true; vector<int> ls; for(int i=2;i<=r;i++){ if(prime[i]){ ls.push_back(i); for(int j=2;j*i<=r;j++) prime[j*i]=false; } } vector<int> in; for(int i=0;i<(int)ls.size();i++){ if(l<=ls[i]&&ls[i]<=r) in.push_back(ls[i]); } ls=in; int ret=0; for(int i=0;i<(int)ls.size();i++){ vector<int> num; for(int j=0;ls[i]>0;j++){ num.push_back(ls[i]%10); ls[i]/=10; } vector<int> rev=num; reverse(rev.begin(),rev.end()); if(rev==num) ret++; } return ret; } };
Med FourStrings
問題概要
We have four strings: a, b, c, and d. A superstring of our four strings is any string S such that each of the four strings occurs somewhere in S as a contiguous substring. Note that some superstrings of our four strings always exist. For example, the string S = a+b+c+d is obviously a superstring of a, b, c, and d. Find and return the length of the shortest superstring of a, b, c, and d.
簡単な意訳
文字列a,b,c,dが与えられる。a,b,c,dがすべて部分文字列として含まれるような文字列の内、文字数が最小の文字列の文字数を求めよ。
解法
全て10文字以内なので、a,b,c,dを適当な順に並び替え、その順番で文字列を接続していったときに、文字数が最小になればよい。
aの後ろにbを接続する時、aの左側からループを回していき、最初に接続できると判別できたところでその文字列が接続できる中では必ず最小の文字数になる。
と説明しても分かり辛いのでコード見てください。ちなみにバグを埋め込んだ自分はデバッグに30分以上を費やし、残り5秒あたりで提出。(テストケースを試し終わったのが残り7秒だったので、合っているか確認できませんでした)それでも通ってくれたので嬉しい。
#include <bits/stdc++.h> using namespace std; class FourStrings{ public: string func(string a,string b){ string c=a+b; for(int i=0;i<(int)b.size();i++){ if(a[0]==b[i]){ int end=0; bool flag=true; for(int j=1;i+j<(int)b.size()&&j<(int)a.size();j++){ end++; if(a[j]!=b[i+j]){ flag=false; } } if(flag){ int n=a.size()+b.size()-end-1; cout<<n<<endl; if(n<(int)c.size()){ if(n==a.size()) return a; if(n==b.size()) return b; c.clear(); for(int j=0;j<=i;j++) c+=b[j]; for(int j=1;j<n-i;j++) c+=a[j]; return c; } } } } return c; } int shortestLength(string a,string b,string c,string d){ string ans=a+b+c+d; vector<int> per; for(int i=0;i<4;i++) per.push_back(i); vector<string> s; s.push_back(a); s.push_back(b); s.push_back(c); s.push_back(d); do{ string tmp=func(s[per[1]],s[per[0]]); for(int i=2;i<4;i++){ tmp=func(s[per[i]],tmp); } cout<<tmp<<endl; if(ans.size()>tmp.size()) ans=tmp; }while(next_permutation(per.begin(),per.end())); return ans.size(); } };
と自分はここで時間切れ。
一応hardも。
Hard PalindromePath
問題概要
You are given an undirected graph with n nodes, labeled 0 through n-1. You are given the description of its edges in vector
簡単な意訳
連結である保証のないn頂点からなるグラフが与えられる。vector
解法(解いてないので合っている保証は全くありません)
まず、始点と終点に繋がる辺を見る。この時点で同じ文字の辺の組み合わせが無ければ答えはありません。もしその組み合わせがあれば、次は始点・終点からその辺の組み合わせに沿って1歩ずつ移動した後の地点で。再帰的にやっていけば最終的に同じ頂点に辿り着くOR地点が入れ替わるところまでいったらそれが答え。BFSをおすすめします。
(しかし時間内に終わるか怪しい)
感想
1055→1085(+30)でした。6回しかやっておらず、しかも最初の3回はバッチテストの見方を間違えて悲惨な目に。最後の2回でグレーからここまで戻ってこれたので良かった。来年は早いうちにグリーンから昇格したい。