本文共 9366 字,大约阅读时间需要 31 分钟。
2020牛客寒假算法基础训练营2
A.做游戏(思维)
题意:两个人玩石头剪刀布,牛牛出石头a次,剪刀b次,布c次,牛可乐出石头x次,剪刀y次,布z次,问牛牛最多可以赢多少次
题解:对牛牛每次可以赢的出法取最小值即可
代码:
#include #include #include #include #include #include #include #include #include
B.排数字(思维)
题意:给定一个由纯数字构成的字符串,你可以随机排列这些数字,问你排出的字符串最多包含多少个“616”子串,61616这样的算两个
题解:最好的情况肯定是“61616”这样排列,结果就是6和1的数量取最小值。
代码:
#include #include #include #include #include #include #include #include #include
C.算概率(DP)
题意:一共n道题,每道题做对的概率为pi,问做对0-n道题的概率分别是多少,结果对1e9+7取模
题解:\(dp_{i,j}\)表示前i道题做对了j道,则有状态转移方程\(dp_{i,j}\) = \(dp_{i-1,j}\)x(1-\(p_i\))+\(dp_{i-1,j-1}\)x\(p_i\),注意j=0的特殊情况,时间复杂度O(\(n^2\))
代码:
#include #include #include #include #include #include #include #include #include
D.数三角(极角排序)
题意:给定n个不重复的点,求一共可以组成多少个钝角三角形
题解:对每个点进行极角排序后双指针找上下界统计钝角数量
代码:
#include #include #include #include #include #include #include #include #include
E.做计数(完全平方数)
题意:给定一个n,问有多少个不同的三元组{i,j,k},满足\(\sqrt{i}+\sqrt{j} = \sqrt{k}\),i,j,k均为正整数,且i * j <= n,i,j,k有一者不同即为不同
题解:展开算式可得 i + j + 2\(\sqrt{ij}\) = k,可见i*j必须是完全平方数,枚举n以内的完全平方数,再枚举其因数即可
代码:
#include #include #include #include #include #include #include #include #include
F.拿物品(贪心)
题意:对于n个物品,每个物品都有一个a值和b值,牛牛和牛可乐依次选择这n个物品,每次从剩下的里面选一个,牛牛先选,牛牛最后的权值为选择物品的a值总和,牛可乐的权值为选择的物品的b值总和,两者都希望自己的权值最大,在两者的最优选择方案下两者会如何选择
题解:贪心,两者都尽量选择a+b值大的物品,可以理解成削弱你就是增强我、
代码:
#include #include #include #include #include #include #include #include #include
G.判正误(hash)
题意:给定t组a,b,c,d,e,f,g,a-g的范围在int内,判断\(a^d + b^e + c^f = g\)是否成立
题解:直接计算肯定是会TLE的,这里我选择了快速幂%1e9+7这个神奇的数字居然过了,跟出题人所描述的方法不太相同,也不太理解这道题目的意义
代码:
#include #include #include #include #include #include #include #include #include
H.施魔法(DP)
题意:一共n个元素,第i个元素的值为ai,每次从中最少选择k个元素,费用是每次选中的元素的极差,每个元素只能选择一次,求最小花费
题解:先从小到大排序,选择方案一定是连续的一系列数,并且选择次数越多花费越小,假设将这个数列切割m次,每次切割都会使最大花费减少切割位置左右两个元素的差值,比如在i位置切割,花费会减少\(a_{i+1} - a_i\),这样即可得到状态转移方程,dp[i] = \(max_{j\in[1,i-k]}\){dp[j]}+d[i],dp[i]表示在位置i处切割后最多减少的花费,d[i]表示在i位置切割减少的花费,其中最大值可以在计算中维护,时间复杂度O(n)
代码:
#include #include #include #include #include #include #include #include #include
I.建通道(二进制)
题意:给定n个点,每个点都有一个权值v,两点之间建立一条路的花费为lowbit(v1\(\bigoplus\)v2),问连通所有点的最小花费
题解:将权值相同的点去重,设去重后有m个点,接着利用&和|运算统计出所有权值中二进制中既有1又有0的位数,找到最小的二进制第k位,结果就是\(2^k*(m-1)\)
代码:
#include #include #include #include #include #include #include #include #include
J.求函数(线段树)
题意:有n个一次函数,第i个函数f(i) = \(k_i\)*x+\(b_i\),有m次操作,每次操作分两种
1 i k b 将\(f_i(x)\)修改为\(f_i(x) = k*x+b\)
2 l r 求\(f_r(f_{r-1}(...f_{l+1}(f_l(1))...))\),答案对1e9+7取模
题解:对于第二种操作所求结果可以计算为
\[\prod_{i=l}^rk_i+\sum_{i=l}^rb_i*\prod_{j=i+1}^rk_j\]
需要注意的使当j=i+1>r时按\(\prod_{j=i+1}^rk_j\) = 1计算。
那么对于上式,我们可以采用两棵线段树分别维护加号左右的两个式子,重点就是如何合并这两个区间
对于区间[l,r],我们把它分成两部分\([l_1,r_1]\),\([l_2,r_2]\),令式子\(\prod_{i=l_1}^{r_1}k_i = n1\),\(\prod_{i=l_2}^{r_2}k_i = n2\)
\(\sum_{i=l_1}^rb_i*\prod_{j=i+1}^rk_j\) = m1,\(\sum_{i=l_2}^rb_i*\prod_{j=i+1}^rk_j\) = m2,那么合并区间时,加号左边部分的合并方法就是 \(n1*n2\),加号右侧的合并方法是\(m1*n2+m2\),注意这些式子累加符号的上限仍然是r
代码:
#include #include #include #include #include #include #include #include #include
转载地址:https://www.cnblogs.com/cloudplankroader/p/12275042.html 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!