Q1. 程式交易
想法
第一天先買,維護一個 bool 變數,分為有持股與無持股兩種情況。
- 有持股->若當前價格>=當初買的價格(tp)+D,賣掉,tp 改為當前股價
- 無持股->若當前價格<=當初賣的價格(tp)-D,買起來,tp 改為當前股價
細節
若交易結束仍持有股票,則不考慮該股票買進的成本 -> 賣掉的時候再加上獲利
實作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| #include<bits/stdc++.h> using namespace std;
bool iss=true; int n,sum,d,tp;
int main(){ ios::sync_with_stdio(0);cin.tie(0);
cin>>n>>d>>tp;
for(int i=1;i<n;++i){ int now; cin>>now; if(iss && tp+d<=now){ sum+=now-tp; tp=now; iss=false; }else if(!iss && tp-d>=now){ tp=now; iss=true; } }
cout<<sum<<"\n"; }
|
Q2. 贏家預測
想法
將輸贏判斷抽象化,方便除錯。其餘依照題目用 vector 模擬即可。
實作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
| #include<bits/stdc++.h> using namespace std;
#define siz(v) ((int)v.size()) using ll=long long;
struct player{
ll s,t,f; };
player ps[1005]; int n,m;
bool battle(int a,int b){ bool ret=(ps[a].s*ps[a].t)>=(ps[b].s*ps[b].t); if(ret){ ll tps=ps[a].s+(ps[b].s*ps[b].t)/(2*ps[a].t); ll tpt=ps[a].t+(ps[b].s*ps[b].t)/(2*ps[a].s); ps[a].s=tps; ps[a].t=tpt;
ps[b].s+=ps[b].s>>1; ps[b].t+=ps[b].t>>1; ps[b].f++; }else{ ll tps=ps[b].s+(ps[a].s*ps[a].t)/(2*ps[b].t); ll tpt=ps[b].t+(ps[a].s*ps[a].t)/(2*ps[b].s); ps[b].s=tps; ps[b].t=tpt;
ps[a].s+=ps[a].s>>1; ps[a].t+=ps[a].t>>1; ps[a].f++; } return ret; }
int main(){ ios::sync_with_stdio(0);cin.tie(0);
cin>>n>>m; for(int i=1;i<=n;++i) cin>>ps[i].s; for(int i=1;i<=n;++i) cin>>ps[i].t;
vector<int> bt(n); for(int i=0;i<n;++i) cin>>bt[i];
while(siz(bt)>1){ vector<int> vt,fl; for(int i=0;i<siz(bt);i+=2){ if(i==siz(bt)-1){ vt.emplace_back(bt[i]); }else{ if(battle(bt[i],bt[i+1])){ vt.emplace_back(bt[i]); if(ps[bt[i+1]].f<m) fl.emplace_back(bt[i+1]); }else{ if(ps[bt[i]].f<m) fl.emplace_back(bt[i]); vt.emplace_back(bt[i+1]); } } }
while(bt.size()) bt.pop_back();
for(auto i:vt) bt.emplace_back(i); for(auto i:fl) bt.emplace_back(i); }
cout<<bt.front(); }
|
Q3. 數位占卜
前言
這是我唯一沒有滿分的題目,要用 set<long long>
陣列,還要 rolling hash 。 參考資料:2022 01/09 APCS 題解 - HackMD
實作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84
| #include<bits/stdc++.h> using namespace std;
using ll=long long; const ll MOD=2147483647; const ll X=29;
ll pwt[105],inv[105];
ll h[50010][105];
string s[50010];
set<ll> ss[105];
ll POW(ll a,ll x){ ll ret=1; while(x>0){ if(x&1) ret=ret*a%MOD; a=a*a%MOD; x>>=1; } return ret; }
void build(){ pwt[0]=inv[0]=1; for(int i=1;i<=101;i++){
pwt[i]=X*pwt[i-1]%MOD;
inv[i]=POW(pwt[i],MOD-2); } }
void hah(string &tp,ll p){ int m=tp.size();
h[p][0]=tp[0]-'a'+1; for(int i=1;i<m;++i){ h[p][i]=(h[p][i-1]+(tp[i]-'a'+1)*pwt[i])%MOD; } ss[m].insert(h[p][m-1]); }
ll query(ll p,ll l,ll r){ return l==0 ? h[p][r] : (h[p][r]-h[p][l-1]+MOD)%MOD*inv[l]%MOD; }
ll solve(int n){ ll ans=0; for(int i=0;i<n;++i){ ll m=s[i].size(); for(int j=1;j<m;++j){
if(j*2<=m) continue;
if(query(i,0,m-j-1)==query(i,j,m-1)){
if(ss[j*2-m].count(query(i,m-j,j-1))) ans++; } } } return ans; }
int main(){ ios::sync_with_stdio(0);cin.tie(0);
int n; cin>>n; build(); for(int i=0;i<n;++i){ cin>>s[i]; hah(s[i],i); }
cout<<solve(n)<<"\n"; }
|
Q4. 牆上海報
想法
Greedy + 二分搜。避免有人不知道要搜什麼,是搜尋高度。因為從題目中我們可以發現 -> 越高的地方可以放東西的區間越來越破碎,也越來越少。且若 x 是可以放的下的高度,選 x\‘< x 都不會更好(題目要求越高越好)。這樣就可以一次刪除一半的區間。
那 Greedy 呢?因為有規定擺放順序,因此能放就放,這個區間放不下就移至下個區間。沒有區間可以放就表示這個高度不合法。
實作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
| #include<bits/stdc++.h> using namespace std;
int n,k; int h[200010],bd[50010];
bool check(int x){ int psum=0; vector<int> len; for(int i=1;i<=n;++i){ if(h[i]>=x){ psum++; }else{ len.emplace_back(psum); psum=0; } }
len.emplace_back(psum);
for(int i=1,j=0;i<=k;++i){ while(len[j]<bd[i]){ j++; if(j==len.size()) return false; } len[j]-=bd[i]; } return true; }
int main(){ ios::sync_with_stdio(0);cin.tie(0);
cin>>n>>k; for(int i=1;i<=n;++i) cin>>h[i]; for(int i=1;i<=k;++i) cin>>bd[i];
int l=0,r=1073741824; while(r-l>1){ int mid=l+r>>1; if(check(mid)){ l=mid; }else{ r=mid; } }
cout<<l<<"\n"; }
|