Codeforces #106 (Div. 2)
練習として全問解いてみました
A問題
大きい順に使っていく貪欲法
k=gets.to_i a=gets.split.map(&:to_i) a=a.sort.reverse t=0 ans=0 a.each{|s| break if t>=k t+=s ans+=1 } ans=-1 if t<k && ans==12 p ans
B問題
変換してみて確認する.
基数が35より大きくなることがあるので注意
BASE="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; def getv(s) return BASE.index(s); end def convert(s,b) res=0 0.upto(s.length-1){|i| return -1 if getv(s[i])>=b res*=b res+=getv(s[i]) } return res end def check(a,b,r) return false if convert(a,r)==-1 || convert(b,r)==-1 a=convert(a,r) b=convert(b,r) return false if a<0||a>=24||b<0||b>=60 return true end a,b=gets.split[0].split(":") ans=[] for r in 2..100 ans.push(r) if check(a,b,r) end if ans.length==0 then puts 0 elsif check(a,b,101) then puts -1 else ans.each{|i| puts i } end
C問題
差が大きくなりすぎないように貪欲に使っていく
わたしは交互に取るという方法で解いた.
#include <cstdio> #include <cmath> #include <cstring> #include <cstdlib> #include <climits> #include <queue> #include <stack> #include <algorithm> #include <list> #include <vector> #include <set> #include <map> #include <iostream> #include <deque> #include <complex> #include <string> #include <numeric> #include <iomanip> #include <sstream> #include <bitset> #include <valarray> #include <iterator> using namespace std; typedef long long int lli; typedef unsigned int uint; typedef unsigned char uchar; typedef unsigned long long ull; #define REP(i,x) for(int i=0;i<(int)(x);i++) #define FOR(i,c) for(__typeof((c).begin())i=(c).begin();i!=(c).end();i++) #define RREP(i,x) for(int i=(x);i>=0;i--) #define RFOR(i,c) for(__typeof((c).rbegin())i=(c).rbegin();i!=(c).rend();i++) int dx[4]={-1,0,1,0},dy[4]={0,-1,0,1}; //左 上 右 下 typedef pair<int,int> P; const int INF=0x20000000; const double EPS=1e-8; int n; P a[111111]; int maxa; int sum=0; int dp[111111]; int main(){ cin>>n; REP(i,n){ cin>>a[i].first; a[i].second=i; } sort(a,a+n); //maxa=*max_element(a,a+n); int x=n/2; int y=n-x; //sum=accumulate(a,a+n,0); cout<<y<<endl; for(int i=0;i<n;i+=2){ cout<<a[i].second+1<<" "; } cout<<endl; cout<<x<<endl; for(int i=1;i<n;i+=2){ cout<<a[i].second+1<<" "; } cout<<endl; }
D問題
区間DP
#include <string> #include <iostream> #include <vector> #include <algorithm> #include <cstring> using namespace std; #define REP(i,x)for(int i=0;i<(int)x;i++) string in; typedef long long lli; const lli MOD=1000000007; lli dp[701][701][3][3]; lli rec(lli s,lli e,lli left,lli right){ lli ans=0; if(dp[s][e][left][right]>=0) return dp[s][e][left][right]; if(s==e)return 1; //左側と右側と決める lli depth=0; lli exit=0; for(lli i=s;i<e;i++){ if(in[i]=='('){ depth++; }else{ depth--; } if(depth==0){ exit=i+1; break; } } //左に色を塗る for(lli i=1;i<3;i++){ if(i==left)continue; ans=(ans+rec(exit,e,0,right)*rec(s+1,exit-1,i,0))%MOD; } //右に色を塗る for(lli i=1;i<3;i++){ if(exit==e&&right==i)continue; ans=(ans+rec(exit,e,i,right)*rec(s+1,exit-1,0,i))%MOD; } return dp[s][e][left][right]=ans; } int main() { memset(dp,-1,sizeof(dp)); cin>>in; cout<<rec(0,in.size(),0,0)<<endl; return 0; }
E問題
KMP法
#include <cstdio> #include <algorithm> #include <iostream> #include <vector> using namespace std; #define REP(i,x)for(int i=0;i<(int)x;i++) string s,in; int n,m; vector<int> matching(){ vector<int> ans(in.size(),99999999); vector<int> fail(in.size()); //KMPテーブル fail[0]=0; int st=0; for(int j=1;j<(int)in.size();j++){ while(st>0&&in[j-1]!=in[st-1]){ st=fail[st-1]; } st++; if(in[j]!=in[st-1])fail[j]=st; else fail[j]=fail[st-1]; } int i=0; for(int k=0;k<n;k++){ while(i>=0&&s[k]!=in[i]){ i=fail[i]-1; } if(i>=0)ans[i]=min(ans[i],k-i); if(i==(int)in.size()-1)break; i++; } return ans; } int solve(){ if(in.size()==1)return false; vector<int> t1=matching(); reverse(s.begin(),s.end()); reverse(in.begin(),in.end()); vector<int> t2=matching(); REP(i,t2.size()){ if(t2[i]<99999999)t2[i]=s.size()-t2[i]-1-i; //cout<<t2[i]<<endl; } reverse(s.begin(),s.end()); for(int i=1;i<(int)in.size();i++){ int j=in.size()-i; if(j-1>=0&&t1[i-1]<99999999&&t2[j-1]<99999999){ if(t1[i-1]+i<=t2[j-1]){ return true; } } } return false; } int main() { cin>>s; n=s.size(); int ans=0; cin>>m; REP(i,m){ cin>>in; ans+=solve(); } cout<<ans<<endl; return 0; }