# 112年度學科能力競賽竹北高中校內初選題解 ###### by ocean ------------------------------------ [題目](https://drive.google.com/file/d/1P4hZYuNl4UgONtiu3R-hFMxe1ZXCuGgP/view?usp=sharing) ## 第一題 排序後,隔一個分組 :::spoiler code ```c++= #include<bits/stdc++.h> #define int long long using namespace std; int32_t main(){ ios::sync_with_stdio(0); cin.tie(0);cout.tie(0); int num[10]; int a = 0, b = 0; for(int i=0;i<10;i++) cin>>num[i]; sort(num, num+10); for(int i=0;i<10;i++){ if(i % 2) b += num[i]; else a += num[i]; } cout<<b<<" "<<a<<"\n"; return 0; } ``` ::: ## 第二題 因為本次比賽並無時間限制,所以硬爆是可行的:) ~~對 我硬爆我驕傲~~ 但我可以提供一些想法 ![](https://hackmd.io/_uploads/Hy7Po4wC2.png) 可以發現是外圈往內數的,並且每次皆為左上開始,可以依據這個規律寫出答案 :::spoiler 硬爆code ```c++= #include<bits/stdc++.h> using namespace std; int main(){ ios::sync_with_stdio(0); cin.tie(0);cout.tie(0); int n, i, j;cin>>n>>i>>j; int num[n+1][n+1] = {}; int op = 1; int x=1, y=1, k = 2; num[1][1] = 1; // cout<<(n/2 + (n % 2))<<" "<<(n / 2 + 1)<<"\n"; while(y != (n/2 + (n % 2)) or x != (n / 2 + 1)){ if(op == 1){ if(y+1 <= n and num[x][y+1] == 0){ y++; num[x][y] = k++; }else op++; }else if(op == 2){ if(x+1 <= n and num[x+1][y] == 0){ x++; num[x][y] = k++; }else op++; }else if(op == 3){ if(y-1 > 0 and num[x][y-1] == 0){ y--; num[x][y] = k++; }else op++; }else if(op == 4){ if(x-1 > 0 and num[x-1][y] == 0){ x--; num[x][y] = k++; }else op=1; } // cout<<x<<" "<<y<<"\n"; } /*for(int i=1;i<=n;i++){ for(int j=1;j<=n;j++){ cout<<num[i][j]<<" "; } cout<<"\n"; }*/ cout<<num[i][j]<<"\n"; return 0; } ``` ::: ## 第三題 利用while(cin>>)迴圈或者getline(cin, )簡單模擬 :::info 分數加法公式 a/b + c/d = (a\*d + b\*c)/b\*d ::: :::spoiler code ```c++= #include<bits/stdc++.h> #define int long long #define f first #define s second using namespace std; pair<int, int> a; string s; char op; int32_t main(){ // ios::sync_with_stdio(0); // cin.tie(0);cout.tie(0); cin>>s; int i=0; for( ;i<s.size() and isdigit(s[i]);i++){ a.f *= 10; a.f += s[i] - '0'; } i += 1; for( ;i<s.size() and isdigit(s[i]);i++){ a.s *= 10; a.s += s[i] - '0'; } // cout<<a.f<<" "<<a.s<<"\n"; while(cin>>op){ cin>>s; pair<int,int> b; int i=0; for( ;i<s.size() and isdigit(s[i]);i++){ b.f *= 10; b.f += s[i] - '0'; } i += 1; for( ;i<s.size() and isdigit(s[i]);i++){ b.s *= 10; b.s += s[i] - '0'; } // cout<<a.f<<" "<<a.s<<" "<<b.f<<" "<<b.s<<"\n"; if(op == '+'){ a.f = a.f*b.s + a.s*b.f; a.s = a.s * b.s; }else if(op == '-'){ a.f = a.f*b.s - a.s*b.f; a.s = a.s * b.s; } int p = __gcd(a.f, a.s); a.f /= p; a.s /= p; if(a.s < 0){ a.s *= -1; a.f *= -1; } } cout<<a.f<<"/"<<a.s<<"\n"; return 0; } ``` ::: ## 第四題 dp經典題,也可以說是費氏數列加強版 dp[0] = 1 dp[1] = 1 dp[2] = 2 dp[i] = dp[i-1] + dp[i-2] + dp[i-3] :::spoiler code ```c++= #include<bits/stdc++.h> #define int long long using namespace std; int32_t main(){ ios::sync_with_stdio(0); cin.tie(0);cout.tie(0); int n;cin>>n; int dp[n+1] = {}; dp[0] = 1; dp[1] = 1; dp[2] = 2; for(int i=3;i<=n;i++) dp[i] = dp[i-1] + dp[i-2] + dp[i-3]; cout<<dp[n]<<"\n"; return 0; } ``` ::: ## 第五題 題目中說道 ![](https://hackmd.io/_uploads/Hyyq6NDCh.png) 很明顯就算有限時間硬爆也是一個可行解 利用next_permutation排出所有運算符號的運算順序 最好的方法是利用struct實作 ~~但因為我懶,所以使用set實作~~ :::spoiler code ```c++= #include<bits/stdc++.h> #define int long long using namespace std; string s; int ans = -1e9; char op[50]; int ord[50]; vector<int> num(51); int32_t main(){ ios::sync_with_stdio(0); cin.tie(0);cout.tie(0); for(int i=0;i<50;i++) ord[i] = i; cin>>s; int i=0; for( ;i<s.size() and isdigit(s[i]);i++){ num[0] *= 10; num[0] += s[i] - '0'; } int a = 1, b = 0; for( ;i<s.size();i++){ if(isdigit(s[i])){ for( ;i<s.size() and isdigit(s[i]);i++){ num[a] *= 10; num[a] += s[i] - '0'; } a++; i--; }else op[b++] = s[i]; } // cout<<a<<" "<<b<<"\n"; // for(int i=0;i<a;i++) cout<<num[i]<<" "; // cout<<"\n"; // for(int i=0;i<b;i++) cout<<op[i]<<" "; // cout<<"\n"; do{ // for(int i=0;i<50;i++) cout<<ord[i]; // cout<<"\n"; set<int> st; vector<int> tmp = num; for(int i=0;i<=b;i++) st.insert(i); for(int i=0;i<b;i++){ auto it = st.lower_bound(ord[i]); if(op[*it] == '-') tmp[(*next(it))] = tmp[(*it)] - tmp[(*next(it))]; else if(op[*it] == '+') tmp[(*next(it))] = tmp[(*it)] + tmp[(*next(it))]; else if(op[*it] == '*') tmp[(*next(it))] = tmp[(*it)] * tmp[(*next(it))]; st.erase(ord[i]); // for(int i:st) cout<<tmp[i]<<" "; // cout<<"\n"; } ans = max(tmp[b], ans); }while(next_permutation(ord, ord+b)); cout<<ans<<"\n"; return 0; } ``` :::