20230128比赛题解(杭州四中)
前言
这个比赛的题解本来应该是林某写的,但是因为林某想要摆烂,所以这个任务就被委托(推卸)到我身上了。
由于笔者是高一学生,高一年级上半学期没开技术课,我之前碰 Python 还是小学三四年级的时候,想来有五六年没写了,现在 Python 是不敢写也不会写。所以以下的代码都不是 Python,而是 Haskell(我在学习的语言)。
本文事起仓促,有的题目来不及写 std,所以只有文字题解请见谅。
1.random
如果想要赢,显然你摇出的数字要大于等于朋友摇出数字中较大的那个。所以比出较大那个输出这个值到 6 的所有数(以空格分开)即可。
main = do
[x, y] <- fmap (map read . words) getLine
let l = max x y
putStrLn $ foldl (\acc x -> acc ++ show x ++ " ") [] [l .. 6]2.clap
很简单的一个容斥题,输出的答案显然是高一同学 n 秒内鼓掌时刻和高二同学 n 秒内鼓掌时刻的并集,所以将两个集合相加减去交集即可,公式是:
main = do
[x, y, n] <- fmap (map read . words) getLine
print ((n `div` x) + (n `div` y) - (n `div` lcm x y))3.count
对每门课取平均,然后回到列表中一一比较,算出超过的人数即可。
import Control.Monad (replicateM)
import Data.List (transpose)
check :: [(Double, Int)] -> Int
check [] = 0
check (x : xs)
| fst x > realToFrac (snd x) = check xs
| otherwise = 1 + check xs
main = do
[a, _] <- map read . words <$> getLine
d <- replicateM a $ map read . words <$> getLine
let aver = (/ realToFrac a) <$> (realToFrac <$> (sum <$> transpose d))
let ans = check . zip aver <$> d
putStr $ foldl (\acc x -> acc ++ show x ++ "\n") [] ans4.coin
先读清楚题目是第一周,第二周……。然后利用等差数列求和公式大致判断出 n 在第几周,然后在对应的那一周里面再判断即可。
5.number
显然如果一个数正着和反着是相同的,那么这个数是回文数。所以先将读入的数(最好使用字符串形式,因为这样子倒过来方便,事实上字符串形式对解决问题并没有影响,因为字符串的排序和数字的排序方式是差不多的)倒置进行判断是否是回文数,然后对剩下的值进行打擂,得到的最大值即为回文数。
import Control.Monad
import Data.List
main = do
n <- read <$> getLine
nums :: [String] <- replicateM n getLine
putStrLn $ maximum (filter (\x -> x == reverse x) nums)6.jump
贪心即可。每次在自己可以跳的范围内选最远的那颗石头,最后跳的次数即为答案
7.money
仍然贪心即可。将这些同学按照需要的钱数升序排序,然后从头开始加,加到不能再加为止,此时的人数即为答案。
8.candy
本题思路是超纲的,结果可能不一定超纲。
大致思路是:将每一个点都考虑为图中的一个节点,然后这个节点具有一个值,然后对相邻的节点进行建边(建完会发现是个二分图,甚至是个 DAG),然后对这个 DAG 进行拓扑排序,算出各个节点值即可。
具体做法和代码见底下评论区。