A. 這是一道簽到題
題目的背景是基於簡單的博弈論Nim遊戲,但細心者可以發現小明和小美的名字的首字母一致,所以只需要進行讀入,直接輸出"XM"即可透過本題
#include<stdio.h>
int n, x;
void solve()
{
scanf("%d", &n);
for (int i = 1; i <= n; i++) scanf("%d", &x);
puts("XM");
}
int main()
{
int T = 1;
scanf("%d", &T);
while (T--) solve();
return 0;
}
B. ACMer
判斷每一組中1的個數是否大於2,如果大於2,則數量加一
#include<stdio.h>
int n, x, cnt = 0;
void solve()
{
int sum = 0;
for (int i = 0; i < 3; i++) // 讀入三個數字
{
scanf("%d", &x);
sum += x;
}
if (sum >= 2) cnt++;
}
int main()
{
int T;
scanf("%d", &T);
while (T--) solve();
printf("%d\n", cnt);
return 0;
}
C. Stock Exchange(Easy Version)
觀察題目我們發現資料的範圍非常的小,1 ≤ n ≤ 2000,因此我們可以採取時間複雜度為 \(O(n^2)\) 的演算法,也就是暴力的列舉每一個區間,尋找哪一對天數的股票價值的差最大。
#include<iostream>
const int N = 2010;
int n, a[N];
int max(int a, int b) // 比較 a b 大小並返回最大值的函式
{
return a >= b ? a : b;
}
void solve()
{
scanf("%d", &n);
for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
int ans = 0;
for (int i = 1; i <= n; i++)
for (int j = i + 1; j <= n; j++)
{
ans = max(ans, a[j] - a[i]);
}
printf("%d\n", ans);
}
int main()
{
int T = 1;
while (T--) solve();
return 0;
}
D. Stock Exchange(Hard Version)
觀察題目我們發現n的資料範圍非常的大,因此我們不能再使用時間複雜度為\(O(n^2)\)的演算法,而只能使用時間複雜度為\(O(n)\)或者\(O(n logn)\)的演算法。
而對於本題我們想到貪心,在一次遍歷的過程中動態地修改最小值,並計算最大值。
#include<iostream>
const int N = 1e6 + 10;
int n, a[N];
int min(int a, int b)
{
return a >= b ? b : a;
}
int max(int a, int b)
{
return a >= b ? a : b;
}
int main()
{
scanf("%d", &n);
int Min = 1e9, ans = 0;
for (int i = 1; i <= n; i++)
{
scanf("%d", &a[i]);
Min = min(Min, a[i]);
ans = max(ans, a[i] - Min);
}
printf("%d", ans);
return 0;
}
E. /\
沒啥好說的,注意跳脫字元 \
#include<stdio.h>
int main()
{
printf("/\\");
return 0;
}
F. BOX
簡單的幾何問題,如果給定點的三個座標值都在長方體的三個座標值確定的範圍之內,則該點在盒子中。
#include<stdio.h>
class Point // 筆者寫幾何類題目的時候比較喜歡定義一個類 Point 表示點
{
public:
int x, y, z;
void read() { scanf("%d%d%d", &x, &y, &z); } // 定義一個函式使得讀入更方便
};
int z0, h, u0, v0, u1, v1;
int min(int a, int b)
{
return a > b ? b : a;
}
int max(int a, int b)
{
return a > b ? a : b;
}
bool check(Point p)
{
if (p.z >= z0 && p.z <= z0 + h
&& p.x >= min(u0, u1) && p.x <= max(u0, u1)
&& p.y >= min(v0, v1) && p.y <= max(v0, v1))
return 1;
return 0;
}
void solve()
{
scanf("%d%d%d%d%d%d", &z0, &h, &u0, &v0, &u1, &v1);
int q;
scanf("%d", &q);
while (q--)
{
Point p;
p.read(); // 讀入點的座標;
puts(check(p) ? "YES" : "NO"); // 如果滿足在盒子內部則輸出"YES"
// 這裡的語法可能用的比較繁瑣,能理解就行
}
}
int main()
{
int T = 1;
while (T--) solve();
return 0;
}
G. 數學考試
思維題。
-
首先要能發現,當\(n\),\(m\)是偶數時,即可以一半 \(1\) 為正數,一半 \(1\) 的負數,組內消化掉。
-
當 \(n\) 是奇數時,即當 \(1\) 的個數是奇數的時,顯然 \(n - 1\) 是偶數,那麼 必然能把 \(n - 1\) 個 \(1\) 分成 \((n - 1) / 2\) 組,那麼每組中的兩個 \(1\), 一個前面是 "+" ,一個前面是 "-" ,則一定可以把 \(n - 1\) 個 \(1\) 抵消掉,無論 \(2\) 有多少個,也無法與最後剩下的那個奇數 \(1\) 相消,得證:當 \(n\) 為奇數是, 一定無法使陣列之和等於 \(0\)。
-
當 \(2\) 的個數\(m\)是奇數時,當且僅當 \(1\) 的個數為偶數,且 \(1\) 個數不為 \(0\) 才可以存在兩個 \(1\) 和多出來的那個 \(2\) 相消。
而除此之外的所有情況都存在一種可能性使得陣列的元素之和等於 \(0\).
#include<stdio.h>
void solve()
{
int n, m;
scanf("%d%d", &n, &m);
if (n & 1) // 判斷是奇數
{
puts("NO");
return;
}
if (m % 2 && !n) // n == 0 而且 m 是奇數
{
puts("NO");
return;
}
puts("YES");
}
int main()
{
int T;
scanf("%d", &T);
while (T--) solve();
return 0;
}
H. 200個數字
首先想到使用陣列 cnt[i] 記錄 數字i 出現的個數。
其次我們發現數字i可能是負數,那麼增加一個偏移量就行了,譬如 偏移量 C = 110,那麼此時 cnt[10] 記錄就是 -100 出現的個數 計算公式如 -100 + C = 10;
此時從高向低遍歷一遍,找到出現次數最多的數字,由於從高向低遍歷,則一定滿足該數字是出現次數一樣多的數字裡面的最大的。
#include<stdio.h>
const int C = 110; // 偏移量
int cnt[400], n;
void solve()
{
scanf("%d", &n);
for (int i = 1; i <= n; i++)
{
int x;
scanf("%d", &x);
cnt[x + C]++;
}
int Max = 0, ans = -1e9;
for (int i = -100 + C; i <= 100 + C; i++)
{
if (Max <= cnt[i])
{
Max = cnt[i];
ans = i - C;
}
}
printf("%d\n", ans);
}
int main()
{
int T = 1;
while (T--) solve();
return 0;
}