程序員進階之算法練習(xí)(十三)

前言

比賽就在這周末,這篇是比賽前最后一篇訓(xùn)練總結(jié)。

正文

hdu 5980(簡單題)

題目大意

一個32位的數(shù)字,每個bytes包括8bit,所以一個整數(shù)是由4bytes組成;
現(xiàn)給出n個數(shù)字,問組成數(shù)字的bytes中,有多少個'a'。

Sample Input
3
97 24929 100
Sample Output
3

題目解析

對于每個數(shù)字,用0x000000ff進行與操作,取出最后8位,然后與'a'判斷,然后右移8位,知道數(shù)字為0即可;

hdu 5978(簡單題)

題目大意

一個盒子里有k個紅球,1個黑球,兩個人輪流從盒子取球(不放回),取出紅球者勝出;
現(xiàn)在給出k,要求:
輸出0表示,先后手一樣的勝率;
1表示,先手有優(yōu)勢;
2表示,后手有優(yōu)勢;
k = 10^5

Sample Input
1
2

Sample Output
0
1

題目解析

容易知道,
k=1的時候,先手優(yōu)勢;
k=2的時候,均勢;
k=3的時候,先手優(yōu)勢;
k=4的時候,均勢;
接著推導(dǎo),
k=5的時候,又是先手優(yōu)勢;k=6的時候,還是均勢;
猜想,根據(jù)奇偶性即可判斷結(jié)果。

驗證:
用sg函數(shù)來表示,sg[i]=0表示均勢,sg[i]=1表示先手優(yōu)勢,sg[i]=2表示后手優(yōu)勢;
如果sg[i]=0,那么有sg[i+1]=1,因為k=i+1的時候,多了1/(i+1)的直接獲勝概率;
如果sg[i]=1, 那么有sg[i+1]=0,因為k=i+1的時候,先手有1/k的概率直接獲勝,后手有(k-1)/k * (1 / (k-1))=1/k的概率直接獲勝,剩下的是均勢;

hdu 5934

題目大意

有n個炸彈,給出炸彈的坐標(x[i], y[i]), 爆炸的范圍r[i], 引爆的代價c[i];
(如果爆炸的范圍內(nèi)有炸彈,也會被引爆)
求n個炸彈引爆的最小代價;
n=1000

Sample Input
1
5
0 0 1 5
1 1 1 6
0 1 1 7
3 0 2 10
5 0 1 4

Sample Output
Case #1: 15

樣例數(shù)據(jù)解釋:
1 樣例數(shù)量
5 n個炸彈
0 0 1 5 x[i], y[i], r[i], c[i]

題目解析

(你可能只需引爆部分炸彈,如果某些炸彈考得比較接近)

一開始用貪心,策略如下:
記錄前i個引爆的最小代價,ans[k] = 1,表示第k個炸彈是主動引爆;
對于第i個炸彈,有兩種可能:主動引爆和被動引爆;

  • 主動引爆的最小代價:對于前面i-1個炸彈中ans[k]=1,且在i的爆炸范圍內(nèi)的炸彈,可以不引爆,算出i個炸彈的引爆最小代價sum1;
  • 再看被動引爆的最小代價:從前面i-1個炸彈中,選擇能引爆i,且代價最小的一個點,作為引爆i的點;然后把i能引爆的點優(yōu)化掉,算出sum2;

比較sum1和sum2,得出當前最優(yōu)解。
但是
中間WA了幾次,發(fā)現(xiàn)這種策略無法保證正確性,于是換一種思路:
對于炸彈,我們分成幾類:

  • 1、兩兩能相互引爆;
  • 2、A能引爆B,B不能引爆A;
  • 3、A和B是獨立的;

容易知道,對于類型1,只需選擇一個最小的引爆;類型2要選擇引爆鏈的最前端(A->B->C);對于類型3,兩個都要引爆;
最終做法:
按照炸彈的引爆范圍建圖,如果A能引爆B,那么連A到B的邊;
遍歷有向圖,把強連通分量縮點;
最后把所有入度為0的點的cost相加即可得到答案;

hdu 5937

題目大意

給出1~9,9個數(shù)字的數(shù)量;
從數(shù)字中,每次選3個數(shù)字組成a+b=c,只要有一個數(shù)字不同,視為不同的等式,每個數(shù)字只能用一次;
問最多組成多少個等式;
每個數(shù)字不超過100個。

input
1 1 1 1 1 1 1 1 1

output
2

解釋:最多有 1+2=3, 和 4+5=9兩種。

題目解析

總共有:
8種:1+1/2/3/4/5/6/7/8=2/3/4/5/6/7/8/9..
7種:2+1/2/..../7
..
到最后的
1種:8+1=9
總共有36種,其中1+2=3 和 2+1=3 是相同的;
于是有(36 - 4) / 2 + 4 = 20種; (4種是1+1, 2+2, 3+3, 4+4)
給20個等式編號;
dp[[i] 表示狀態(tài)i,其中二進制位為1表示取該位數(shù)對應(yīng)的等式;總共有2^20個狀態(tài);
狀態(tài)轉(zhuǎn)移:
如果i+(1<<k)合法,則有 dp[i+(1<<k)]=dp[i]+1;

ans = max(dp[i]);

復(fù)雜度:
O(2^20 * 20);

但是無法解決1+2=3 和 2+1=3的問題;

在上面的基礎(chǔ)上,改用搜索,直接枚舉所有的可能。
添加一個剪枝:當目前搜的解無法比之前更優(yōu)時返回;

hdu 5943

題目大意

(s+1,s+2,?,s+n) n個數(shù),放在1~n的位置上,第i個數(shù)字必須滿足x[i] % i == 0.問能不能放。

例如:s=3, n=8
4 ~ 11 總共8個數(shù),可以這么放:

 1   2   3    4   5 6 7 8
 11 10   9    4   5 6 7 8

s 和 n的范圍是1e9。

題目解析

題目的數(shù)據(jù)很大,但是容易知道,對于區(qū)間[l, r]內(nèi)地的素數(shù),只能放在1上面,那么如果區(qū)間內(nèi)存在兩個素數(shù),即無解,于是可以這么做:
重疊的部分可以對齊放;
不重疊的部分,如果存在2個質(zhì)數(shù),無解;
小于1000的部分,用匈牙利算法;

這部分是隊友推出的結(jié)論,我就直接認為大于1000個就無解。

hdu 5971

題目大意

n個人,m個1對1的比賽,每次比賽都是goodPlayer vs badPlayer;
給出x個goodPlayer 和 y個badPlayer;
詢問:
是否每個人在比賽中或者在給出的x、y內(nèi);
是,輸出Yes;
否,輸出No;

N (1 ≤ N≤ 1000)、M(1 ≤M ≤ 10000)、X,Y(X+Y≤N )

Sample Input
5 4 0 0
1 3
1 4
3 5
4 5
5 4 1 0
1 3
1 4
3 5
4 5
2
Sample Output
NO

YES

題目解析

題目意思不清楚,根據(jù)樣例猜測:
首先希望每個人在比賽中合法,同時與給定的good、bad不沖突,最后每個人都在比賽中 或者 在制定的good、bad中;

于是可以這么做:
用vis[i] 來表示第i個人的狀態(tài):
vis[i] = 0 表示未知數(shù);
vis[i] = 1 表示good;
vis[i] = -1 表示bad;

按照題目給出的x、y個人標志1和-1;然后按照這些人的比賽進行dfs;
然后再遍歷n個人,如果這個人在比賽中,并且目前還未標志,給他隨意標記為good,然后dfs;

最后看n個人是否全部vis[i] != 0即可;

hdu 5975

題目大意

n個數(shù),q個操作。
給出一個通項公式:f(x) = lowbit(x),然后給出操作:
1 l r , 詢問區(qū)間[l,r] 的區(qū)間和;(f[i]的和, i = l ~ r)
2 x, 詢問樹狀數(shù)組中,修改x的需要修改幾次值;

n≤1018,q≤105

題目解析

暴力推出解:

 x  1   2   3   4   5   6   7   8   9   10  11  12
    1   2   1   4   1   2   1   8   1   2   1   4

容易推出:
前n項和由1、2、4、8等組成,其中1的間隔是2,2的間隔4,4的間隔8,這樣暴力算一遍即可;

總結(jié)

喜歡簡單點的生活,怕麻煩,懶;
也是怕失敗,不太愿意堅持,不太愿意嘗試。
總覺得自己年輕,實際上不久就到而立之年;
總是計較自己做的事情,是不是對以后有幫助,是好還是壞呢?
修養(yǎng)了半年多,明年可以一拼。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容