【题解】2020牛客寒假算法基础集训营第二场

2020-2-17 G 题数据已加强但未重测此前提交。

A. 做游戏

尽可能让 牛牛的每次出 剪刀/石头/布 对应到 牛可乐出 布/剪刀/石头。

时间复杂度

42841945

B. 排数字

以外不需要考虑。

要让 子串最多一定是 ,这样后面的串可以用前面的 ,数量为 。(可以理解为前面一个 后面 循环)

时间复杂度

42857464

C. 算概率

表示前 道题做对 道的概率

转移时考虑第 道题是否做对,转移方程为:
时间复杂度

42841954

D. 数三角

一个三角形的三边长 最长 )满足 (或存在两条边向量的点积 ),则该三角形为钝角三角形。

枚举三个点判断即可,注意判断共线和不要算重。

时间复杂度

42841973

E. 做计数

两边平方,得 ,显然仅当 都是整数且 为完全平方数时才会对应一个符合条件的

枚举 中所有的完全平方数(完全平方数可以表示为 ,只需要枚举 ),再枚举这个完全平方数的因数,统计答案。

枚举完全平方数 枚举因数,时间复杂度 ,可以进一步优化。

42841984

F. 拿物品

假设物品已经被选完,此时 牛牛选择的物品 属性的价值和是 , 牛可乐选择的物品 属性价值和是

如果 牛牛的 物品与 牛可乐的 交换,则 ,对于 牛牛(目标是最大化 )来说会变得更优仅当 化简就能得到),对于 牛可乐也一样。所以两人都会优先选择 最大的物品。

将物品按照两个属性的和从大到小排序,依次分给两人即可。

除排序时间复杂度

42842001

G.判正误

直接计算会 TLE / MLE ,考虑在模意义下进行计算,若 ,则原式有概率成立,多选择一些模数以提高正确率。

42842014

H.施魔法

先将元素按能量值排序,下文默认已排序。

可以证明存在一个最优方案,满足每个魔法一定消耗一段连续的元素。

表示用掉前 个元素的最小代价。

图片说明

维护 的前缀最小值就能 转移了。

DP 过程时间复杂度

42842367

I.建通道

首先将权值去重(权值相等的点连接代价为 ),设去重后有 个点,接下来找到最小的二进制位 ,满足存在 的这个二进制位是 且存在 的这个二进制位是 ,答案就是 (相当于所有这位是 的点与 点连边,是 的点与 点连边)。

排序和去重以外时间复杂度 ,没有卡 ,好像两个 也过了。

42852180

J. 求函数

注意: 时视

对加号左右分别用线段树维护,考虑如何合并两个相邻区间

区间

一棵线段树维护 ,另一棵维护 即可。

同阶,时间复杂度

42842027


C 题:不太懂为什么这么少人过。UPD:好像是因为不懂模意义下运算...emmmmmmm

D 题:使用浮点数请考虑精度问题 ,没 eps 说卡精度就有点那啥..。

G 题:考虑到这个题卡固定模数比卡字符串哈希轻松很多(只要让结果是模数的 lcm 即可)就卡了一些模数,有一些数据不知为何没传上去;使用 math 库中的 pow 函数可以通过,是真的没想到(由于 Yes 的数据都比较有特点,可能被编译器优化了)。以及请不要再纠结哪个模数能AC哪个不能,因为模数相比最终结果小太多,很多模数可能被卡(不管是不是刻意),应该做的是多选一些模数。

以及可能还有一些小问题影响了做题体验,这里说声抱歉

关于样例强度:没有任何义务提供强样例

推锅:赛时提问的回答有个别态度不好,那不是我

有其他问题请在评论中提出~

全部评论
验题人前来报道,表示验题人并不会做最后3题
12 回复 分享
发布于 2020-02-06 18:21
C 题可以用分治 FFT做到 $O(n \log^2 n)$  https://ac.nowcoder.com/acm/contest/view-submission?submissionId=42843674
6 回复 分享
发布于 2020-02-06 18:47
J 只要考虑到函数的复合运算有结合率就可以直接用线段树维护那个函数了。应该和题解是一个意思。
3 回复 分享
发布于 2020-02-06 18:32
42844583蒟蒻求解答,D题为什么这样只能过50的数据????
2 回复 分享
发布于 2020-02-06 19:20
多久没写代码,越来越菜了,做法都比题解复杂多了,尤其是J题没开四倍,菜死了,卡到自闭😭,C题比较好,E题最开始是题解的想法因为写错了,我以为有可能根号处理一个0.5用4ij是完全平方数写了。
2 回复 分享
发布于 2020-02-06 18:33
您好,博主,您出的题很棒!我想问您G题计算a^b % m,先令 a' = (a % m + m) ,在计算a' ^ b % m 为什么是等价的啊?您能告诉我嘛
1 回复 分享
发布于 2020-02-07 18:17
请问为啥G题我这样写也过了,是这个题目的数据的问题吗?   ll n1=pow(a,d);   ll n2=pow(b,e);   ll n3=pow(c,f);
1 回复 分享
发布于 2020-02-07 16:12
问下I题,哪个题解k是用来求有多少不相同的数吗? 我用set代替就过不了啊,只能过85.7%; for(int i=1;i<=n;i++){         cin>>a[i];         se.insert(a[i]);     }     int s1=0,s2=0x7fffffff;     for(int i=1;i<=n;i++){         s1|=a[i];//找出二进制位有1的位置         s2&=a[i];//找出二进制位都为1的位置     }     s2^=s1;//找出二进制位有1但不都为1的位置     ll ans;     int t=se.size()-1;     for(int i=0;i<=30;i++){         int c=1<<i;         if(s2&c){//找出s1二进制位的为1的最小位置             ans=1ll*c*t;                break;         }     }
1 回复 分享
发布于 2020-02-07 13:23
int Pow(int a, int b, int c) {   int ret = 1;   while (b) {     if (b & 1) ret = ret * 1ll * a % c;     a = a * 1ll * a % c;     b >>= 1;   }   return ret; } 您好,我想问G题,为什么这一段代码可以代替乘方,是怎么实现的呢
1 回复 分享
发布于 2020-02-07 12:15
正如您所见。初学OI爆零记
点赞 回复 分享
发布于 2020-02-06 18:43
J题俺是用线段树维护矩阵乘法过的,感觉会更好写一些?
1 回复 分享
发布于 2020-02-06 18:24
请问下A题我这样写和标称有什么区别吗,这个过不了,标程用的min 。ll sum = A>=Y?Y:A + B>=Z?Z:B + C>=X?X:C;   还有1e9为什么不开 ll 过不了
点赞 回复 分享
发布于 2020-12-29 19:35
H题中间的一些区间不会被分割到小于k吗
点赞 回复 分享
发布于 2020-02-21 01:29
题解真的好
点赞 回复 分享
发布于 2020-02-13 10:36
f题可以维护两次 牛牛是a-b 牛可乐是b-a 这样做吗?会不会太麻烦了 还要标记是不是用过了
点赞 回复 分享
发布于 2020-02-10 21:52
H题的状态转移方程能这样写吗
点赞 回复 分享
发布于 2020-02-10 19:10
哈哈哈菜鸡前天还在埋怨样例给的不好,今天就被解释给酷到了~
点赞 回复 分享
发布于 2020-02-08 13:53
请问大神,G题判正误为什么一定要对a,b,c用ff函数处理一下呢
点赞 回复 分享
发布于 2020-02-07 16:09
请问一下 I题  for(inti = 1; i <= n; i++) {     va &= v[i];     vo |= v[i];   } va^=vo; 再用求得的va找到最小满足的lowbit位  这里为什么可以这样求得va呢 没有太理解
点赞 回复 分享
发布于 2020-02-07 14:48
请问为何统计不重复元素个数的时候,这样写就错了。 #include <bits/stdc++.h> using namespace std; typedef long long ll; #define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); const int maxn = 2e5 + 5; #define lowbit(x) (x)&(-x) int a[maxn]; int main() { ios; int n; cin >> n;    ll ans; for (int i = 0; i < n; ++i) cin >> a[i]; sort(a, a + n); // int tot = unique(a, a + n) - a; int v1 = 0, v0 = 0x7fffffff; for (int i = 0; i < n; ++i) { v1 |= a[i]; v0 &= a[i]; } /*int tot = 0; for (int i = n - 1; i >= 0; --i) tot += (a[i] != a[i + 1]);*/     int tot = unique(a, a + n) - a; // 这里--------------为啥这么写错了 // int k = lowbit(v1 ^ v0); for (int i = 0; i <= 30; ++i) { int cur = 1 << i; if (cur & (v1 ^ v0)) { ans = 1LL * cur * (tot - 1); //这里------为何在这里输出ans就错了,放在最后才能ac break; } }     cout << ans << endl; }
点赞 回复 分享
发布于 2020-02-07 14:15

相关推荐

03-28 19:11
铜陵学院 C++
有礼貌的山羊追赶太阳:太典了,连笔试都没有开始就因为HC满了而结束了,而且还卡你不让你再投其他部门的。
点赞 评论 收藏
分享
评论
32
34
分享

创作者周榜

更多
牛客网
牛客企业服务