【队内训练】ICPC2016大连题解

ICPC2016大连
A UVALive 7723 Wrestling Match(带权并查集) 325 / 1045
B UVALive 7724 Regular Number(shift-and算法) 34 / 296(赛后过掉)
C UVALive 7725 Game of Taking Stones(java二分) 65 / 328(赛后过掉)
D UVALive 7726 A Simple Math Problem(推公式) 363 / 1339
E UVALive 7727 Aninteresting game(树状数组原理考察) 51 / 196(赛后过掉)
F UVALive 7728 Detachment (推公式) * 242 / 878 *
G UVALive 7729 Garden of Eden(点分治) * 82 / 304*(赛后过掉)
H UVALive 7730 To begin or not to begin(签到) 487 / 739
I UVALive 7731 Convex(签到)**483 / 653**
J UVALive 7732 Find Small A(签到) 479 / 952
K UVALive 7733 Guess the number 31 / 117
题解:
HIJ:sb题(J题注意2^8=256 =_=||)
A:带权并查集
因为本题目只有两种状态,不是好就是坏。所以总的状态就只有0,1两种。
find函数回溯的时候sum[x]=(sum[x]+sum[t])%2,t是x的初始祖先节点;
在加入并查集时,fx=find_(x),fy=find_(y),当fx!=fy时sum[fy]=(sum[x]-sum[y]+1+2)%2;
当相同时需要判断是否符合sum[x]!=sum[y],不符合说明有阵营不明确的人
另外本题还有一个注意点,有些并查集只有自己一个节点,这种情况下也是
不明确的人,所以需要用cnt数组记录每个并查集中节点数目。
最后一个注意点,有可能是加入并查集没有错误,但是最后可能一个并查集中
有些点在好的阵营中,另外在坏的阵营中,需要将这种情况排除掉
https://paste.ubuntu.com/p/rBtqr2JWD7/
G:点分治算法
问你有多少对(u,v),使得在此路径上的种类数有k个
点分治就是基于树上的节点进行分治。
点分治的本质其实是将一棵树拆分成许多棵子树处理,并不断进行。
这其中有两个部分是不变的,一个是计算重心,一个是对子树进行路径的计算或者记录状态
剩下的就是在总的dfs下,计算通过当前根节点的路径上的信息(一般计数题目是总体计算然后剪去合并的冲突项,有些问满足条件的最长路径是遍历过程中不断寻找最大值)
本题目一个注意点就是在计算当前子树的满足条件的路径数时,为了降低复杂度
用下面这种方式,其实s0=(s0-1)&sta[i],这个操作可以实现对sta[i]的1的遍历
比如与10010或等于11111的最小的数时1101,然后是1111,之后是11101,最后是11111
实际模拟一遍就知道怎么回事了
https://paste.ubuntu.com/p/2dxdYph2zX/

for(int s0=sta[i];s0;s0=(s0-1)&sta[i])  res+=cou[((1<<k)-1)^s0];

D:推公式
题目给出两个等式:
X+Y=A X + Y = A
LCM(X,Y)=B L C M ( X , Y ) = B
我们可以看出A,B的GCD也就是X,Y的GCD
我们首先让两个等式同时除以 GCD(A,B) G C D ( A , B )
便得到:
X1+Y1=A/GCD(A,B) X 1 + Y 1 = A / G C D ( A , B )
X1Y1=B/GCD(A,B) X 1 ∗ Y 1 = B / G C D ( A , B )
X1GCD(A,B)=X,Y1GCD(A,B)=Y X 1 ∗ G C D ( A , B ) = X , Y 1 ∗ G C D ( A , B ) = Y
解方程求出X1,Y1,乘以GCD(A,B)即可
https://paste.ubuntu.com/p/3CJP22CBt8/
C.高精度
威佐夫博弈只要满足

(5+1)2(MaxMin)=Min ( 5 + 1 ) 2 ∗ ( M a x − M i n ) = M i n

所以只要大数+java二分高精度求出 5 5 就可以了。
https://paste.ubuntu.com/p/twsbyFXPJT/
E.树状数组
首先我们要深刻理解树状数组的内部原理
我们先来看一下每个数的二进制码和它们对应的lowbit
树状数组原理
1.lowbit(i)表示i能整除的最大的2的幂次
2.i-lowbit(i)表示跳到前一个整幂次的二进制区间
3.i+lowbit(i)表示跳到下一个包含当前区间的区间
如果知道这三个性质,
我们先来看第一问,求某两段之间的lowbit之和,
我们首先求出 sum(1,i1) s u m ( 1 , i − 1 ) 再求出 sum(1,j) s u m ( 1 , j ) ,前缀和相减就可以了
现在问题变为如何求出 sum(1n) s u m ( 1 − n ) ,我们来看性质1,我们发现我们只要知道
有多少恰好只能整除1的
有多少恰好只能整除2的
有多少恰好只能整除4的….
我们可以发现恰好整除1个数为 [n/1n/2] [ n / 1 − n / 2 ] 向下取整
因为能够整除1的只包含恰好整除1的和能够整除2的
以此类推,我们就可以o(1)的计算出所有2的幂次的贡献,之后就扫一遍算贡献就可以了
单次复杂度是log的
再来看第二问,问某个数被加过几次,想想树状数组的add函数,这个问题就不难想了,每个数字只会在包含他的区间被重新添加,我们只要观察性质三,就很容易算出第二问了!于是整个题就解决了。
https://paste.ubuntu.com/p/dTQsG8mfNh/
F.推公式
本题题意就是让一个数拆成多个数之和,而且这些数的乘积最大,我们知道当我们拆的数越多,乘积就越大,然题意要求每个数不重复,所以我们要让这些数尽量靠近,分下面两种情况
1.X=Σni=2iX=9=2+3+4.2i, 1. X = Σ i = 2 n i 例 如 X = 9 = 2 + 3 + 4. 此 时 肯 定 拆 分 为 2 − i , 为 最 大 饱 和 状 态

2.X=Σni=2i+k(k<=n)Kn2+1 2. X = Σ i = 2 n i + k ( k <= n ) 对 于 多 出 来 的 K , 我 们 能 想 到 肯 定 是 从 n 到 2 每 个 不 断 + 1 , 这 样 才 能 保 证 这 些 数 足 够 靠 近 。

根据以上两种情况我们列出等式
X=(2+n)(n1)2nnk(n+1)(n+0)...(nk+2)(nk)(nk1)...1 X = ( 2 + n ) ∗ ( n − 1 ) 2 n 在 这 里 代 表 长 度 解 出 n 之 后 算 出 k , 答 案 就 是 ( n + 1 ) ∗ ( n + 0 ) ∗ . . . ∗ ( n − k + 2 ) ∗ ( n − k ) ∗ ( n − k − 1 ) ∗ . . . ∗ 1 答 案 用 两 个 阶 层 相 除 表 示 就 可 以 了 。

https://paste.ubuntu.com/p/PbSbmttPMK/
B.Shift-And算法
l如果你学过这个算法的话,那么就是模板题。
Shift-And算法解决的就是每个位置可以放很多种字符时的字符串匹配问题
ans数组表示的是有哪些长度即是目标串后缀又是模式串前缀
求模式串在目标串中出现次数的时候
例如11001就代表当前串有长度为1,4,5的串既是目标串后缀又是模式串前缀
所以如果我们想统计模式串出现次数,就是ans[len]=1时答案++;
所以这道题就可以用Shift-And算法结束了!
https://paste.ubuntu.com/p/5S6RNvSvYG/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值