Codeforces Round #589 (Div. 2)

Codeforces Round #589 (Div. 2)

A
刚开始以为有什么奇妙解法,想了3min后发现可以直接暴力搜。(毕竟就个DIV2的A)

B
模拟它的操作即可。
出现冲突的话flag置为0,最后输出0即可。
Main test的时候把我卡掉了…因为我忘记处理连续长度为0的时候与之前某些操作会冲突的可能性了…

D
最开始因为看错了C的题面(没有视力) ,就莽D了…
想了一下后作出这样的算法,先读入所有的边,star存图。然后遍历每一个点,1结点直接放入set1,对于之后的结点我们扫描这个结点所有的相邻点,并且根据这些相邻点所在的集合来确定这个点可以放的集合位置。这里在做的时候其实很朴素,如果有3个可以放,不妨放在set1;如果有2个可以放,不妨放在2,这是因为2和3的地位其实是等价的(因为我们是顺序的放结点进来,所以不会出现前面的会影响后面的情况);如果有1个可以放,那么显然只能放在这里(必要条件)。所有节点都处理完后我们就成功地把所有点进行了集合的分划,时间复杂度是O(m)。不过在此之前有一个地方要注意,如果这个图是不联通的,那么肯定是不能满足题意的(可以通过对前一个大联通块占据1、2、3个集合进行分类考虑),此处就不再赘述。判断联通性可以使用并查集。
上述的操作处理后,要进行一下final_check,具体说来就是满足题意中的:两个集合中的任意两个点之间都要有一条边。对于某一个集合(不妨考虑1),它应该对外连有x * (y + z)条边,其中x、y、z是集合1、2、3的大小。而我们只需要用计数器cnt记录一下这个集合中所有点的邻边个数即可,这是因为我们对于集合的构造保证了这些点的邻边都不是本集合的元素,时间复杂度也是O(m)。这样子只需要比较cnt和邻边要求值就可以知道有没有对于任意一对点都全部连上了边。

最后总结一下就是:冰茶几判联通 + 扫一遍做构造 + 比较个数判对应

C
看完D后看了下C…我瞎了…最后要求的不是 ∑f ,而是 ∏f …人傻了…那就很好做了…
我们先构造出sqrt(1e9)的素数表,然后获得x的所有素因子。题目要求的是对1-n的每一个数对x的每一个因子作函数乘法,等价于对x的每一个因子对1-n的每一个数作函数乘法,从而考虑p在1-n中出现的幂次即可。同样的,我们做一个 轮换,不考虑某一个数对p的贡献,而是考虑pi会由哪些数贡献。显然,在1-n中,有且仅有n / pi 个数会对其贡献,那么算出cnt后不断求快速幂即可。
有一个地方有坑,i的终止条件是pi > n,但是如果n比较大的时候,有pi < n && pi+1爆long long,所以最好考虑商的形式。我最开始想了一下用n / p < now,但是不好,边界有重叠问题;heavyshower指点用n / now < p,相当有道理。不过对比了这两种商后就会发现他们的边界是对偶的,这是一个显而易见但是极其有用的结论,以后遇到边界有问题的情况时交换一下分母可能就会漂亮很多。

溢出问题
当时以为ll溢出后会直接到负数,所以判的条件是: now *= p; if(now > n || now < 0) break;
单步调试后发现多跑了一步,是因为721273330206403129(满足条件的最后一个数字,再乘p就会爆ll并且会超过n) * 947 = 516312978210353371,这显然已经是溢出了。
在这里插入图片描述
仔细回忆一下大一学的c语言感觉知道哪里错了…因为溢出的处理是截断,所以溢出后的值是不是个负数其实不好保证,正负号是取决于那个真值的二进制表示下最高位是1还是0…这个坑以后记住了…

后补:无符号数的溢出才是截断!对于有符号数的溢出是未定义行为


愉快的深夜下分环节…
2000+的rank居然只掉了12分还算可以

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值