標籤:組合 cout etl ++ mes break href 構造 oid
IOI2018 組合動作
UOJ
首先顯然可以兩次試出首字母
考慮增量構造
假設首字母為A,且已經試出前i個字母得到的串s
我們考慮press這樣一個串s+BB+s+BX+s+BY+s+XA
首先這個串長不超過4N
其次由於首字母不重,返回的ans只會等於i+2,i+1,i三者中的一個
如果是i+2,那麼顯然可以確定第i+1個字母為B,因為XA一定不會產生2的貢獻(A是首字母)
如果是i+1,那麼第i+1個字母一定是X
如果是i,那麼第i+1個字母一定是Y
剩下首字母為B,X,Y的情況類似構造
我們一直使用上述方法試到第n-1個
最後再兩次試出最後一個字母即可
這樣的總次數是2+(n-2)+2=n+2次
下面是提交代碼:
#include<bits/stdc++.h>#include "combo.h"using namespace std;string f[7],ans;void getf(string fir){ if(fir=="A"){f[0]+="BB";f[1]+="BX";f[2]+="BY";f[3]+="XA";f[4]+="Y";f[5]+="B";f[6]+="X";} if(fir=="B"){f[0]+="AA";f[1]+="AX";f[2]+="AY";f[3]+="XB";f[4]+="Y";f[5]+="A";f[6]+="X";} if(fir=="X"){f[0]+="AA";f[1]+="AB";f[2]+="AY";f[3]+="BX";f[4]+="Y";f[5]+="A";f[6]+="B";} if(fir=="Y"){f[0]+="AA";f[1]+="AB";f[2]+="AX";f[3]+="BY";f[4]+="X";f[5]+="A";f[6]+="B";}}void getfir(){ int sc=press("AB"); if(sc){ int x=press("A"); if(x)ans+='A'; else ans+='B'; } else{ int x=press("X"); if(x)ans+='X'; else ans+='Y'; }}void getlas(int n){ int sc=press(ans+f[4]); if(sc==n)ans+=f[4]; else{ sc=press(ans+f[5]); if(sc==n)ans+=f[5]; else ans+=f[6]; }}string guess_sequence(int n){ getfir(); if(n==1)return ans; getf(ans); for(int i=2;i<=n-1;i++){ string now=""; now+=ans+f[0]+ans+f[1]+ans+f[2]+ans+f[3]; int x=press(now); if(x==i+1)ans+=f[0][0]; if(x==i)ans+=f[3][0]; if(x==i-1)ans+=f[4]; } getlas(n); return ans;}
給大家提供一個手寫的press用於調試
int press(string ss){ int l=ss.length(),res=0; for(int i=0;i<l;i++){ int js=0; for(int j=0,k=i;j<L;j++,k++) if(ss[k]==S[j])js++; else break; res=max(res,js); }//cout<<ss<<' '<<res<<endl; return res;}
[IOI2018]組合動作