题意:给定整数 n n n ,胖教授想将 1 ∼ n 1∼n 1∼n 这 n n n 个数字分成两组,每一组至少有一个数,并且使得两组数字的和的最大公约数最大,请输出最大的最大公约数。
思路:首先 1 ∼ n × ( n + 1 ) 2 1\sim \frac {n\times (n+1)} 2 1∼2n×(n+1) 的任意一个数都能被这些数表示,那么问题转化为有两个正整数满足 a + b = m = n × ( n + 1 ) 2 a+b=m= \frac {n\times (n+1)} 2 a+b=m=2n×(n+1) ,最大化 gcd ( a , b ) \gcd(a,b) gcd(a,b)
我们由辗转相除法的定义推一下式子 gcd ( a , b ) = gcd ( a , m − a ) = gcd ( a , m ) \gcd(a,b)=\gcd(a,m-a)=\gcd(a,m) gcd(a,b)=gcd(a,m−a)=gcd(a,m) , a a a 的取值为 a ∈ [ 1 , m − 1 ] a\in[1,m-1] a∈[1,m−1] ,那么问题转化为找到 m m m 的最大因子,根号枚举找一下最小质因子即可。
AC代码:http://oj.daimayuan.top/submission/317961
题意:
题解:(数学) 代码源每日一题 Div1 历法
思路:和 这道题 挺像的。抽象一下:找到一对
x
,
y
x,y
x,y 满足
0
≤
x
,
y
<
m
i
n
(
m
,
d
)
0\leq x,y
总结了一下:
有连续的 n n n 个整数,那么这些整数在模 p p p 意义下,按照同余系的大小分为两种:
AC代码:http://oj.daimayuan.top/submission/318549
题意:
题解:(贪心/字典树) 代码源每日一题 Div1 删库
思路:字典树上 dfs + 贪心。开始的时候忘了还有字典树这东西了。
首先我们构建字典树。我们选择一个字符串并删去集合中对应的字符串,等价于在字典树上割去某子树,子树上的标记点 ≤ k \leq k ≤k 。
那么贪心思路就是:我们 dfs 完某个节点的儿子后,统计一下该子树上还有多少个标记点。如果标记点 ≤ k \leq k ≤k ,那我们的贪心策略就是直接回溯,不在此节点删除,因为我们回溯后可以和其他兄弟子树上的标记点结合,一起被删去,使得删除次数最小化;反之,我们必须要在此点删除某些儿子子树。我们依次删掉标记点个数最多的子树,使得回溯的标记点更少。
AC代码:http://oj.daimayuan.top/submission/318499
题意:给定长度为 n ( 1 ≤ n ≤ 1 0 6 ) n(1\leq n\leq 10^6) n(1≤n≤106) 的序列 a ( 0 ≤ a ≤ 1 0 6 ) a(0\leq a\leq 10^6) a(0≤a≤106) ,每次操作可以把一个数减一,与这个数相邻的数加一。问最少操作数使得序列 gcd ( a ) ≥ 2 \gcd(a)\geq 2 gcd(a)≥2 。
题解:(枚举/贪心) 代码源每日一题 Div1 不朴素的数列(Bonus)
思路:首先有一个定理:序列的 gcd \gcd gcd 等于序列差分的 gcd \gcd gcd ,即 gcd ( a 1 , a 2 , ⋯ , a n − 1 , a n ) = gcd ( a 1 , a 2 − a 1 , ⋯ , a i − a i − 1 , ⋯ , a n − a n − 1 ) \gcd(a_1,a_2,\cdots,a_{n-1},a_n)=\gcd(a_1,a_2-a_1,\cdots,a_i-a_{i-1},\cdots,a_n-a_{n-1}) gcd(a1,a2,⋯,an−1,an)=gcd(a1,a2−a1,⋯,ai−ai−1,⋯,an−an−1) 。同理,序列的 gcd \gcd gcd 等于序列前缀和的 gcd \gcd gcd 。
我们对序列的相邻数的操作等价于对前缀和序列单点加或减。我们枚举 s u m sum sum 的因子 x x x ,问题转化为操作多少次使得每个前缀都是 x x x 的倍数, ∑ i = 1 n − 1 min ( a i % p , p − a i % p ) \sum_{i=1}^{n-1}{\min(a_i\%p,p-a_i\%p)} ∑i=1n−1min(ai%p,p−ai%p) 。
题解则从一个经典问题类比过来。
给定两个序列 a , b a,b a,b ,也是类似的相邻数加减操作,问对 a a a 至少操作多少次使得与 b b b 完全相等。
定义 s t e p i step_i stepi 表示为前 i i i 个数操作为完全相等的最少次数,那么 s t e p i = s t e p i − 1 + ∣ s a i − s b i ∣ step_i=step_{i-1}+|sa_i-sb_i| stepi=stepi−1+∣sai−sbi∣ 。可以理解为,当前面 i i i 个数操作完之后,会从 a i a_i ai 这个数这里拿走或者送来若干数,我们为了使得 a i = b i a_i=b_i ai=bi ,需要把一些数拿来或者送走若干个数给 a i + 1 a_{i+1} ai+1 ,操作次数就是 ∣ s a i − s b i ∣ |sa_i-sb_i| ∣sai−sbi∣