---
# System prepended metadata

title: 竹北軟研社社內競賽解答

---

# **竹北軟研社社內競賽解答(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";
    }

}
```