# APCS202201 #### 以下非*施工中*程式碼皆由ZeroJudge檢測通過 ## [1. 程式交易](https://zerojudge.tw/ShowProblem?problemid=h081) 紀錄前一次交易的價格&是否有股票 硬算 :::spoiler C++ ```cpp= #include <iostream> using namespace std; int main(){ int n,d,last,cur,had=0,ans=0; cin >> n >> d; cin >> cur; last = cur; had=1; n--; while(n--){ cin >> cur; if (had){ if (cur>=last+d){ had = 0; ans+=cur-last; last = cur; } }else{ if (cur<=last-d){ had = 1; last = cur; } } } cout << ans << "\n"; } ``` ::: :::spoiler Python ```python= n,d = map(int,input().split()) last=10000 had=False ans=0 for cur in map(int,input().split()): if had: if cur>=last+d: had=False ans+=cur-last last=cur else: if cur<=last-d: had=True last=cur print(ans) ``` ::: :::spoiler Python in one line ```python= print((lambda a,l:(lambda n,d,v:max(((bool(v.__setitem__(0,v[0]+c-v[1]))+bool(v.__setitem__(1,c))+bool(v.__setitem__(2,False)) if c>=v[1]+d else 0) if v[2] else (bool(v.__setitem__(1,c))+bool(v.__setitem__(2,True)) if c<=v[1]-d else 0) for c in l))+v[0])(int(a[0]),int(a[1]),[0,10000,False]))(input().split(),map(int,input().split()))) ``` ::: ## [2. 贏家預測](https://zerojudge.tw/ShowProblem?problemid=h082) 照題敘算 :::spoiler C++ 施工中 ```cpp= #include<bits/stdc++.h> using namespace std; int main(){ int n,m; cin >> n >> m; vector<int> s(n),t(n),o(n),h(n,m); for (int i = 0;i<n;i++){ cin >> s[i]; } for (int i = 0;i<n;i++){ cin >> t[i]; } for (int i = 0;i<n;i++){ cin >> o[i]; o[i]++; } while (o.size()>1){ vector<int> ns(n,0),nt(n,0),win,lose; for (int i = 0;i<o.size()/2;i++){ int a = o[i*2]; int b = o[i*2+1]; if (s[b]*t[b]>s[a]*t[a]){ swap(a,b); } h[b]--; ns[a] = s[b]*t[b]/t[a]/2; nt[a] = s[b]*t[b]/s[a]/2; ns[b] = s[b]/2; nt[b] = t[b]/2; win.push_back(a); if(h[b]) lose.push_back(b); } for (int i = 0;i<n;i++){ s[i]+=ns[i]; t[i]+=nt[i]; } o.clear(); for (int p : win){ o.push_back(p); } for (int p : lose){ o.push_back(p); } } cout << (o[0]+1) << "\n"; } ``` ::: :::spoiler Python ```python= n,m = map(int,input().split()) s = [int(text) for text in input().split()] t = [int(text) for text in input().split()] health = [m]*n o = [int(text)-1 for text in input().split()] while len(o)>1: win=[True]*n for i in range(len(o)//2): p1=o[i*2] p2=o[i*2+1] p1,p2=(p1,p2) if s[p1]*t[p1]>=s[p2]*t[p2] else (p2,p1) d=s[p2]*t[p2]//2 s[p1],t[p1]=s[p1]+d//(t[p1]),t[p1]+d//(s[p1]) s[p2]+=s[p2]//2 t[p2]+=t[p2]//2 health[p2]-=1 win[p2]=False o = [i for i in o if win[i]]+[i for i in o if not win[i] and health[i]] print(o[0]+1) ``` ::: :::spoiler Python in one line ```python= print((lambda d:(lambda f:f(f,[d[1]]*d[0]))(lambda F,h:bool((lambda win:(lambda ns,nt:min((bool(d[2].__setitem__(d[4][i],ns[i])) for i in range(len(ns))))+min((bool(d[3].__setitem__(d[4][i],nt[i])) for i in range(len(nt))))+min((bool(h.__setitem__(d[4][i],h[d[4][i]]-(0 if win[i] else 1))) for i in range(len(d[4]))))+bool(d.__setitem__(4,[d[4][i] for i in range(len(d[4])) if win[i]]+[d[4][i] for i in range(len(d[4])) if not win[i] and h[d[4][i]]>0])))([(d[2][d[4][i]] if win[i]>1 else d[2][d[4][i]]+d[2][d[4][i^1]]*d[3][d[4][i^1]]//d[3][d[4][i]]//2) if win[i]>0 else d[2][d[4][i]]+d[2][d[4][i]]//2 for i in range(len(d[4]))],[(d[3][d[4][i]] if win[i]==2 else d[3][d[4][i]]+d[2][d[4][i^1]]*d[3][d[4][i^1]]//d[2][d[4][i]]//2) if win[i] else d[3][d[4][i]]+d[3][d[4][i]]//2 for i in range(len(d[4]))]))([((i^1<len(d[4])) and (d[2][d[4][i]]*d[3][d[4][i]]>d[2][d[4][i^1]]*d[3][d[4][i^1]] or (d[2][d[4][i]]*d[3][d[4][i]]==d[2][d[4][i^1]]*d[3][d[4][i^1]] and i<(i^1))))+2*(i^1==len(d[4])) for i in range(len(d[4]))]))*0+(F(F,h[:]) if len(d[4])>1 else d[4][0]+1)))([int(t) for t in input().split()]+[[int(t) for t in input().split()],[int(t) for t in input().split()],[int(t)-1 for t in input().split()]])) ``` ::: ## [3. 數位占卜](https://zerojudge.tw/ShowProblem?problemid=h083) 用hashset存籤 對於每一個籤,切出不同長度的前後綴,若前綴=後綴 且 剩下的部分能在set裡找到一樣的 則 答案+1 #### 原理: 對於一組聖筊$a+b$ 不失一般性設$a$比較長 所以**a的前半**和**a的後半加b**一樣 設**a的前半**=c、**a的後半**=d $a+b=(c+d)+b=((d+b)+d)+b=(d+b+d)+b$ 可知$d$是$a$的前後綴 所以對每一支籤,切出不同長度的前後綴$d$,只要存在與剩下的部分相同的籤$b$,就可以組成**聖筊** 因為總是用長的籤去找短的籤,所以不用擔心重複算到的問題 :::spoiler C++ ```cpp= #include<bits/stdc++.h> using namespace std; int main(){ int n; cin >> n; unordered_set<string> dat; while (n--){ string s; cin >> s; dat.insert(s); } long long ans = 0; for (string s: dat){ int l = s.size(); for (int i = 1;i<(l+1)/2;i++){ bool sus = true; for (int j = 0;j<i;j++){ if (s[j]!=s[j+l-i]) sus=false; } if (sus){ ans += dat.count(s.substr(i,l-2*i))?1:0; } } } cout << ans << "\n"; } ``` ::: :::spoiler Python ```python= m = int(input()) dat = {input() for a in range(m)} ans = 0 for s in dat: for i in range(1,(len(s)+1)//2): if s[:i]==s[-i:] and s[i:-i] in dat: ans+=1 print(ans) ``` ::: :::spoiler Python in one line ```python= print((lambda dat:str(sum((sum((s[:i]==s[-i:] and s[i:-i] in dat for i in range(1,(len(s)+1)//2))) for s in dat))))({input() for z in range(int(input()))})) ``` ::: ## [4. 牆上海報](https://zerojudge.tw/ShowProblem?problemid=h084) 用貪心法可$O(n)$求出某一高度能否貼海報 能否貼海報$\leftrightarrow$此高度$\le$最大高度$=$答案 且已知答案為$[1,h_{max}]$中的一個整數 對$[1,h_{max}]$二分搜 時間複雜度為$O(n\log_2h_{max})$ :::spoiler C++ ```cpp= #include <bits/stdc++.h> using namespace std; int n,k; vector<int> h,w; bool check(int ans){ int t = 0,len=0; for (int i = 0;i<n;i++){ if (h[i]>=ans) len++; else len = 0; if(len>=w[t]){ len-=w[t]; t++; if(t>=k) return true; } } return false; } int search_ans(int l, int r){ if (l == r) return l; int mid = ((r+l)/2)+1; if (check(mid)){ return search_ans(mid,r); } return search_ans(l,mid-1); } int main(){ ios::sync_with_stdio(false);cin.tie(); cin >> n >> k; h.resize(n); w.resize(k); int mh = 0; for (int i = 0;i<n;i++){ cin>>h[i]; if(h[i]>mh) mh=h[i]; } for (int i = 0;i<k;i++){ cin>>w[i]; } cout << search_ans(1,mh) << "\n"; } ``` ::: :::spoiler Python ```python= n=k=0 h=[] w=[] def check(ans): t = l = 0 for i in range(n): if h[i]>=ans: l+=1 else: l=0 if l>=w[t]: l-=w[t] t+=1 if t>=k: return True return False def search(l,r): if l==r: return l mid = (l+r)//2+1 if check(mid): return search(mid,r) return search(l,mid-1) n,k = map(int,input().split()) h = [int(s) for s in input().split()] w = [int(s) for s in input().split()] print(search(1,max(h))) ``` ::: :::spoiler Python in one line ```python= print((lambda _0,h,w:(lambda c,f:str(f(1,max(h),f,c)))((lambda a:(lambda v:min((bool(v.__setitem__(1,v[1]+1 if i>=a else 0))+(bool(v.__setitem__(1,v[1]-w[v[0]]))+bool(v.__setitem__(0,v[0]+1)) if v[1]>=w[v[0]] else 0) for i in h if v[0]<len(w)))*0+(v[0]>=len(w)))([0,0])),(lambda l,r,F,C:l if l==r else (F((l+r)//2+1,r,F,C) if C((l+r)//2+1) else F(l,(l+r)//2,F,C)))))(input(),[int(s) for s in input().split()],[int(s) for s in input().split()])) ``` :::