# **竹北軟研社社內競賽解答(C++)** ##### by coldspeed --- [題目](https://zerojudge.tw/ShowContest?contestid=15438) ## 第一題: 照做 C++ 解 ```c++= #include <bits/stdc++.h> using namespace std; int main() { int n, m, a; cin >> n >> m; int ans=0; for(int i=0; i<n; i++){ cin >> a; if(a>=m){ ans+=1; } } cout << ans << "\n"; } ``` ## 第二題: 把基數,偶數先分開 排完序後再印出 C++ 解 ```c++= #include <bits/stdc++.h> using namespace std; int main(){ int n, a; cin >>n; vector<int> odd, even; for(int i=0; i<n; i++){ cin >> a; if(a%2){ odd.push_back(a); } else{ even.push_back(a); } } sort(odd.begin(), odd.end()); sort(even.begin(), even.end()); for(int i=0; i<odd.size(); i++){ cout << odd[i] << ' '; } for(int i=0; i<even.size(); i++){ cout << even[i] << ' '; } cout << "\n"; } ``` ## 第三題: 帶入點到線距離公式,記的要加絕對值 ![Screenshot (36)](https://hackmd.io/_uploads/rk_6_83TT.png) C++ 解 ```c++= #include <bits/stdc++.h> using namespace std; int main(){ int x, y, a, b, c; cin >> x >> y; cin >> a >> b >> c; int ans=abs(a*x+b*y+c)/sqrt(a*a+b*b); cout << ans << "\n"; } ``` ## 第四題: 先計算所有數加起來的數**total** 再計算無條件捨去的 **average=total/n** 和餘數**remainder=total%n** 因為要把+1-1的次數做的越少次越好,所以可以把多的remainder給較大的數字。 remainder會把變成的數字變成 average + 1 example: total = 47 average = 5 remainder = 3 原本的數字 : 9 8 8 7 6 3 3 2 2 變成的數字 : 6 6 6 5 5 5 5 5 5 減去平均後 : 4 3 3 2 1 2 2 3 3 (絕對值) 減去值正負 : + + + + + - - - - ### **證明+1, -1 數量一樣:** 以下為了簡化 **pos** = 數字減average是正的總和 (絕對值) **neg** = 數字減average是負的總和 (絕對值) **pos_num** = 數字減average是正的個數 **neg_num** = 數字減average是負或零的個數 ### 例如上面的例子: pos = 13, pos_num = 5 neg = 10, neg_num = 4 ### 可以先由數學得知: **pos - neg = remainder** 一個pos_num數減(average+1) => pos-=1 一個neg_num數減(average+1) => neg+=1 **+1數** = **-1數** : pos - **min(pos_num, remainder)** = neg + **max(0, remainder-pos_num)** ### 三種情況 : **pos_num < remainder:** * pos - pos_num = neg + remainder - pos_num * pos - ~~pos_num~~ = neg + remainder - ~~pos_num~~ * pos = neg + remainder * 可由上面第一式得知**成立** **pos_num > remainder**: * pos - remainder = neg + 0 ( reminder - pos_num < 0 ) * pos = neg + remainder * 可由上面第一式得知**成立** **pos_num = remainder**: * pos - remainder = neg + 0 ( reminder - pos_num = 0 ) * pos = neg + remainder * 可由上面第一式得知**成立** 而最後答案會是 pos - min(pos_num, remainder) C++ 解 ```c++= #include <bits/stdc++.h> using namespace std; #define ll long long int main(){ ll n; cin >> n; ll arr[n], tot=0; for(int i=0; i<n; i++){ cin >> arr[i]; tot+=arr[i]; } ll rem=tot%n, average=tot/n; ll ans, pos=0, pos_num=0; for(int i=0; i<n; i++){ if(arr[i]-average>0){ pos += arr[i]-average; pos_num++; } } ans=pos - min(pos_num, rem); cout << ans << "\n"; } ``` ## 第五題: 原題目:[link]() 如果想要聽的話禮拜三可以問我,抱歉我後面兩題出的有點太難了。 C++ 解 ```c++= #include <bits/stdc++.h> using namespace std; #define ll long long const ll maxn = 3e5+1; ll a[maxn], p[maxn]; vector<ll> v[maxn]; ll dis[maxn]; ll vis[maxn]; ll n; void dfs(ll x){ vis[x]=1; for(int u:v[x]){ dis[u]=dis[x]+1; dfs(u); } } int main(){ cin >> n; for(ll i=1; i<=n; i++){ cin >> a[i]; } for(ll i=2; i<=n; i++){ cin >> p[i]; } for(ll i=2; i<=n; i++){ v[p[i]].push_back(i); } dfs(1); ll ans[n+1]={}; for(ll i=1; i<=n; i++){ if(!vis[i]){continue;} ans[dis[i]]+=a[i]; } ll tot=0; for(int i=n; i>=0; i--){ if(ans[i]!=0){ tot=ans[i]; break; } } if(tot==0){ cout << 0 << "\n"; } else if(tot>0){ cout << "+\n"; } else{ cout << "-\n"; } } ```