# 第一次社內賽題解
problem setter: 賴冠澐,黃博崇
---
<!-- .slide: data-background="https://memeprod.ap-south-1.linodeobjects.com/user-template/178fe997ff2ceba56ec6919dd324f435.png" data-background-opacity="0.5" data-background-size="1000px"-->
### pA. IF倍倍數我
送分題
出題者:黃博崇
----
<!-- .slide: data-background="https://p2.bahamut.com.tw/HOME/creationCover/92/0003700492_B.JPG" data-background-opacity="0.5"-->
照題目做就好了
----
AC code
```cpp=
#include <bits/stdc++.h>
using namespace std;
int main() {
long long a, b;
cin>>a>>b;
if(a%b==0) cout<<a/b;
else cout<<-1;
}
```
---
<!-- .slide: data-background="https://i.pinimg.com/originals/15/8b/ed/158bed9819e4fccf7e18a5eeeaf79c6b.png" data-background-opacity="0.5" data-background-size="1000px"-->
### pB. 階級三角形
出題者:黃博崇
----
其實這題根本出爛了
由於題目設定有問題
你不輸出前面的空格也會給過
----
subtask1
n<=10
~~也出爛了~~
原本想出n<10
不用取模(%)也能拿分
----
subtask2
無額外限制
前面的空格數量會從n-1每行遞減到0
後面的數字會從1每行遞增到n
----
AC code
```cpp=
#include <bits/stdc++.h>
using namespace std;
int main() {
int n;
scanf("%d", &n);
for(int i = 1; i <= n; i++){
for(int j = 0; j < n - i; j++){
printf(" ");
}
for(int j = 1; j <= i; j++){
printf("%d", (n - i + 1)%10);
}
printf("\n");
}
}
```
---
<!-- .slide: data-background="https://p0.itc.cn/images01/20210615/f355ccc8c42d49c8a81a4a48067c9a14.jpeg" data-background-opacity="0.5" data-background-size="1100px"-->
### pC. 這個月砲彈虧損86箱你有頭緒嗎
出題者:黃博崇
----
subtask1
n=1
用一維陣列就能處理
以0,1,-1分別代表沒被炸到的點,被炸到的點,防空炮的點
t=1的砲彈只要考慮落下的座標就可以
t=2的砲彈用迴圈向左右延伸,遇到0就改成1,遇到-1就break
最後計算有幾個1
----
subtask2
無額外限制
用二維陣列
做法和subtask1一模一樣
----
AC code
```cpp=
#include <bits/stdc++.h>
using namespace std;
int n, m, k, w, a, b;
int g[105][105], x[105], y[105], t[105];
int main() {
scanf("%d%d%d%d", &n, &m, &k, &w);
for(int i = 0; i < k; i++){
scanf("%d%d%d", &x[i], &y[i], &t[i]);
}
for(int i = 0; i < w; i++){
scanf("%d%d", &a, &b);
g[a][b] = -1;
}
for(int i = 0; i < k; i++){
if(g[x[i]][y[i]] == -1) continue;
g[x[i]][y[i]] = 1;
if(t[i] == 1){
for(int j = x[i] - 1; j > 0; j--){
if(g[j][y[i]] == -1) break;
g[j][y[i]] = 1;
}
for(int j = x[i] + 1; j <= n; j++){
if(g[j][y[i]] == -1) break;
g[j][y[i]] = 1;
}
}
else{
for(int j = y[i] - 1; j > 0; j--){
if(g[x[i]][j] == -1) break;
g[x[i]][j] = 1;
}
for(int j = y[i] + 1; j <= m; j++){
if(g[x[i]][j] == -1) break;
g[x[i]][j] = 1;
}
}
}
int ans = 0;
for(int i = 1; i <= n; i++){
for(int j = 1; j <= m; j++){
if(g[i][j] == 1) ans++;
}
}
printf("%d", ans);
}
```
---
<!-- .slide: data-background="https://hips.hearstapps.com/hmg-prod/images/220713-delish-seo-01-napoleon-cake-horizontal-v4-080-eb-1658416568.jpg" data-background-opacity="0.5"-->
### pD. 字典人
~~個人覺得題序很有創意~~
出題者:賴冠澐
----
子題1:字典裡的字放進一個陣列,查詢時直接爆搜,沒找到就輸出i
$O(q\times n)$
----
滿分:stl應用,用set或map就可以在$O(\log n)$時間查詢一個字串存不存在。
注意因為字串長度<=15,所以set/map在比對時最多只會比15次,可視為常數。
$O(q\times \log n)$
----
AC code
```cpp=
#include <bits/stdc++.h>
using namespace std;
int main(){
int n, q;
cin>>n>>q;
map<string, int> fd;
for(int i=0;i<n;++i){
string s;
cin>>s;
fd[s]=i;
}
for(int i=0;i<q;++i){
string s;
cin>>s;
if(fd.count(s)==0) cout<<i<<"\n";
}
}
```
---
### pE. 給數學們的電神
怎麼變滅台題QQ
<span style="color:red;">\\whitecatorz/</span>
出題者:賴冠澐
----
子題1:隨便乘一乘就有了
$O(n)$
----
子題2:從小到大枚舉每一種距離,檢查所有人是不是都能跑到這個距離。
$O(n\times k)$
k是要枚舉到多少(~~我現在發現這子題怪怪的~~)
----
怎麼檢查?
1. 從快到慢檢查
2. 如果某人跑完還有剩,就讓給後面的人。如果跑不完,就試試看能不能利用前面剩下的跑完。如果還是不行,就return false
----
滿分:記得基地台那題觀察到的單調性
如果最短距離越長,越不可能被達到,反之越有可能被達到
----
對答案二分搜
$O(n\times \log k)$
k是要枚舉到多少
----
AC code
```cpp=
#include <bits/stdc++.h>
using namespace std;
vector<long long> v;
long long n, x;
bool check(long long k){
long long left=0;
for(long long a:v){
if(a*x>=k) left+=x-(k+a-1)/a;
else left-=(k-a*x+a-1)/a;
if(left<0) return 0;
}
return 1;
}
int main(){
ios_base::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin>>n>>x;
v.resize(n);
for(int i=0;i<n;++i) cin>>v[i];
sort(v.begin, v.end(), greater<long long>());
long long l=1, r=1e15+1;
while(l<r-1){
long long mid=(l+r)>>1;
if(check(mid)) l=mid;
else r=mid;
}
cout<<l<<"\n";
}
```
記得開long long
---
<!-- .slide: data-background="https://image-cdn.essentiallysports.com/wp-content/uploads/forza-horizon-4-bugatti-divo.jpg" data-background-opacity="0.5"-->
### pF. 低山症
不小心出太水QQ
出題者:賴冠澐
----
子題1:枚舉n^2個區間,邊枚舉邊檢查
$O(N^2)$
----
滿分:其實只要記上一次比k小的位直在哪就好,然後不斷更新最長距離
$O(n)$
----
AC code:
```cpp=
#include <bits/stdc++.h>
using namespace std;
int main(){
ios_base::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int n, k;
cin>>n>>k;
vector<int> ar(n+1);
for(int i=1;i<=n;++i) cin>>ar[i];
int j=0, ans=0;
for(int i=1;i<=n;++i){
if(ar[i]<k) j=i;
ans=max(ans, i-j);
}
cout<<ans<<NL;
}
```
---
### final standings
----
top 20:

{"metaMigratedAt":"2023-06-17T13:17:28.157Z","metaMigratedFrom":"YAML","title":"第一次社內賽題解","breaks":true,"slideOptions":"{\"transition\":\"slide\"}","contributors":"[{\"id\":\"9afea478-d7aa-4c3e-a3c7-5db22422f956\",\"add\":5447,\"del\":912},{\"id\":\"07ddd007-4c11-49ca-a607-fc83331a6b9f\",\"add\":856,\"del\":12}]"}