【隊內訓練】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
LCM(X,Y)=B
我們可以看出A,B的GCD也就是X,Y的GCD
我們首先讓兩個等式同時除以GCD(A,B)
便得到:
X1+Y1=A/GCD(A,B)
X1Y1=B/GCD(A,B)
X1GCD(A,B)=X,Y1GCD(A,B)=Y
解方程求出X1,Y1,乘以GCD(A,B)即可
https://paste.ubuntu.com/p/3CJP22CBt8/
C.高精度
威佐夫博弈只要滿足

(5+1)2(MaxMin)=Min

所以只要大數+java二分高精度求出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) 再求出sum(1,j) ,前綴和相減就可以了
現在問題變爲如何求出sum(1n) ,我們來看性質1,我們發現我們只要知道
有多少恰好只能整除1的
有多少恰好只能整除2的
有多少恰好只能整除4的….
我們可以發現恰好整除1個數爲[n/1n/2] 向下取整
因爲能夠整除1的只包含恰好整除1的和能夠整除2的
以此類推,我們就可以o(1)的計算出所有2的冪次的貢獻,之後就掃一遍算貢獻就可以了
單次複雜度是log的
再來看第二問,問某個數被加過幾次,想想樹狀數組的add函數,這個問題就不難想了,每個數字只會在包含他的區間被重新添加,我們只要觀察性質三,就很容易算出第二問了!於是整個題就解決了。
https://paste.ubuntu.com/p/dTQsG8mfNh/
F.推公式
本題題意就是讓一個數拆成多個數之和,而且這些數的乘積最大,我們知道當我們拆的數越多,乘積就越大,然題意要求每個數不重複,所以我們要讓這些數儘量靠近,分下面兩種情況
1.X=Σi=2niX=9=2+3+4.2i,

2.X=Σi=2ni+k(k<=n)Kn2+1

根據以上兩種情況我們列出等式
X=(2+n)(n1)2nnk(n+1)(n+0)...(nk+2)(nk)(nk1)...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/
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章