foj 1982 dp 設其中一個已知
/*
 http://hi.baidu.com/topman3758/blog/item/a19e4af91effb975034f56d2.html
 別人說的簡單dp,我都不會做....#_#

 題目給出一個串n<=1000 串只會出現a,b,c三種字符
 abc或bca可切成一塊
 設最后切出m0個abc , m1個bca,則答案為min{m0,m1}
 求試答案最大

 dp[i,j]表示前面i個字符切出了j個abc,能獲得的最多dp[i,j]個bca

 轉移是看最后這個三個字母是什么
 dp[i-3,j-1]    “abc”
 dp[i-3,j]+1   "bca"
 dp[i-1,j]

 注意dp[i,j]  3*j<=i  , 對于不存在的值不能引用,否則會出錯!!

 貌似這種有兩個要求值的,都是設成一個已知
 如這里前i個,有j個abc
 
*/


zoj 3449

 

/*

一個數字a(最多100000位),本來a = ∑ai*10^i,不斷變為a' = ∑ai*x^i (x=1,2...9) 。

直至a‘<10 ,求此時的a'


比較變化前后的結果,發現變化后減少了∑ai(10^i-b^i)

一開始我就用Java大整數去逼近(減去10^i-b^i),使得結果趨近于10且小于10

超時了


看了watashi的,∑ai*10^i = ∑ai*x^i  (mod 10-x)

“于是我們知道對10-b求模是關于這種運算的不變量,可以發現答案就是b+(n-10)%(10-b)”


其實我之前的那個不斷逼近,其實就是 mod 10 - x 而已,腦殘了?。。?/p>

因為(a^n - b^n) % (a-b) = 0


可以幾位合在再mod會快點

最后結果要不斷加上10-x,使得逼近于10

*/

 

zoj 3450

 

/*

一個定點p0,n個目標點 ,每個目標點有敵人wi,要消滅該點需要ti時間

弱目標點在同一直線,必須先消滅近的才能消滅遠的

問在T時間內最多能消除的敵人


分組背包


注意的是,坐標比較大,用double會精度不夠

看了watashi的做法

他將坐標都除以他們的gcd ,相等的就是同一直線了,而gcd就用來判斷距離了!!

這樣將大數變小了?。。?/p>


注意的是gcd(abs(x),abs(y))要加絕對值

*/


zoj 3451

 

/*

給出足球起點坐標,初速度大小,初速度方向,問球能不能進。

球每碰地一次速度減半


參考watashi的


注意有力量不足的情況

*/

zoj 3453
/*
一列敵人,每個敵人有生命值l[i]
哆啦A夢可以發射m個糖衣炮彈,每個炮彈會攻擊最靠近右邊的且生命值>=ki的敵人
被攻擊的敵人生命值變為1,該敵人會將他的朋友的生命值+1,其朋友區間為a[i],b[i]
如果找不到敵人,則所有敵人生命值+1
求最后生命值最大的

note : 線段樹查找滿足條件的最靠近右邊的寫法
*/

 

 zoj 3354

 

/*

給出一種映射f,問一個序列經過任意次映射的復合,問能得到多少種不同的文本

"he may encrypt the letter for several times. "

here may be ai=aj when i≠j. 不是一一映射

如果是一一映射的,就是一個一個的環了(因為出度、入度為 1)


看watashi的

這題就變成環引出尾巴出來了

答案就成了:max{x[i]} + LCM{y[i]}

x[i]為尾巴長度,y[i]為環長度

注意求x[],y[]數組的方法,用棧


而求LCM時,要分解質因子才行

因為LCM(a%MOD,b%MOD) != LCM(a,b)%MOD

*/

zoj 3456
/*

給出一個圖,每增加一條邊,問能否從0點遍歷所有點回到0點,求最小時間
在一個點有停留時間stay[i],經過邊也有時間,但最多只能經過n-1條不同的邊

題目說了是一棵樹,可以令 邊權 = 2*原邊權+stay[u]+stay[v]
則MST即為答案了

答案是求能否在一年內訪問完,注意有閏年
看watashi寫法的
保留原有MST的邊即可了,新加入的邊,需小于MST的最大邊,才允許加入,然后看能否得到更小的值
但每次下來,只需保留n-1條邊(MST的邊)

*/

 

cf 56E

/*

n張多米諾骨牌排成一行,每一張在位置xi,高度為hi

它倒下的話會影響到[xi,xi+hi-1],問每張骨牌最多能影響右邊的多少張骨牌


令dp[i]表示第i張骨牌能影響到的最遠的骨牌為dp[i]

dp[i] = max{dp[j]}   x[i] <= x[j] <= x[i] + h[i] - 1

則第i張骨牌能影響到的骨牌數目為dp[i] - i + 1

我一開始用線段樹搞,用單調隊列也行


看了別人代碼,神奇,直接算就行了

第i張骨牌,檢查的范圍是[x[i],x[i]+h[i]-1]

如果在檢查過程中發現j,其中dp[j]能影響的最遠范圍已經超過x[i]+h[i]-1的話,就不用再檢查j之后到x[i]+h[i]-1

的骨牌了,因為從x[j]到x[i]+h[i]-1的已經被j考慮過了(也可認為是j到x[i]+h[i]-1最后只會收斂到dp[j])

直接return dp[j]即可

反之,若未超過,則令 j = dp[j] + 1

跳躍性檢查

(認為j到dp[j]收斂到dp[j]了,所以下次檢查dp[j]+1)

*/



CF57D
/*
 題意:n,m的網格,有一些static particles,規定任意兩個不能在同一行、列,不能在相鄰的對角線
  A dynamic particle選擇非static的cell作為起點和終點,然后從起點選擇最短路徑走到終點(不經過
  static particles)。問平均路長

  參見解題報告:                                                                       這里多減了2倍'X'到'X'的,所以要加上
  最后,再加上因為'X'存在要繞路需要多加的距離
*/


CF 58D
/*
 題意:n個單詞(lowercase),先要分成n/2行,每行2個單詞,兩個單詞用分隔符d隔開
 要使得所有行串起來字典序最小,問如何安排每兩行的單詞
 
 分隔符d可以<'a' , > 'z'
 若已知第一個單詞,那么要使字典序最小,第2個單詞肯定是長度為avg-lena中字典序最小的單詞
 avg是每一行兩個單詞的長度和
 
 可以先按照 單詞+d 來排序,然后按從小到大安排
 每個排在前面的單詞,然后加上長度為avg-lena中字典序最小的單詞
*/


SRM 496 PalindromfulString 容斥寫法  ★★★★
/*
 問長度為N的字符串(uppercase)中,至少有K個長度為M的回文串的個數
 N<=11

 一開始我在那里dp推,發現有重復之類的東西不好搞
 看了Sevenkplus的,容斥,感覺好神奇
 
 最多有P = N - M + 1個回文串
 由于規模比較小,枚舉選出哪幾個作為回文串,使得至少有K個,令這個模式為Ti
 (如N = 3, M= 2 , K = 1 ,一個合法的模式為 010)
 則答案為|T0∪T1...∪Tc|,這里就要用到容斥了
 = ∑|Ti|
   -∑|Ti∩Tj|
   +∑|Ti∩Tj∩Tk|
   ...
     直接套用的話復雜度為2^(2^P) ??!

  與平常的容斥有點不一樣,這里存在很多“Tj包含于Ti”,即其交集就是子集了
  如011包含于010
  因為滿足011的肯定滿足010,所以011是010的子集,這里注意了??!二進制枚舉Ti的超集Tj,是模式Ti的子集

  畫個韋恩圖,一個集合Tj要計算的次數就是先減去其余集合Ti在這部分算的次數(減完就為空了),再加上1
  即為 1 - 其余集合Ti在這部分算的次數
 用num[i]表示集合Ti需要算的次數,則num[i] = 1 - ∑num[ii]  ii為i的超集
 for(int j = i+1 ; j < (1<<P) ; j++)
 {
  if((j & i) == i)//j是i的子集
   num[j] -= num[i];
 }
 所以集合Ti對答案的貢獻為 ans += num[i]*26^cnt
 O((2^p)^2)
 cnt為集合Ti獨立變量的個數
 對Ti,求獨立變量的個數,可以先建圖(利用回文串兩端相等的性質),然后dfs算出連通塊的個數就是獨立變量的個數了
*/


TCO'10 Qualification Round 1A 1000pt MegadiamondHunt
/*
 將只含有'<','>'的串,每次去掉<..<>..>連著的幾個
 如果去掉中有n對,則得分為n^2
 求最大得分
 
 一開始以為去掉的順序沒關系,過不了最后一個sample
 看了LayCurse的代碼,它是每次選擇 極大的<..<>..>中最小的一個去掉
 這樣子去貪心...
 如 <<<>><>>
 如果先去掉<<>>,然后剩下<<>> 得分為 2^2+2^2
 但若先去掉<>,則剩下<<<>>> 得分為 1 + 3^2
 因為,考慮一個極大的<..<>..>,若它能擴大,則它的左右肯定先去掉了一個
 極大的<..<>..>,如果已去掉的那個比當前的大,得分是不會比先去掉當前
 這個較小的大,所以每次選極大中的最小那個去掉
*/


zoj 3458
/*
 0 < b - a < 1 + 2sqrt(a)  求 floor(sqrt(a)+sqrt(b))^n % 2(a+b)

 看watashi的,沒接觸過這種問題,做法挺神奇( ⊙ o ⊙ )!

 由 0 < b - a < 1 + 2sqrt(a)
  => 0 < sqrt(b) - sqrt(a) < 1
 令Xn = (sqrt(b)+sqrt(a))^2n = (b+a+2sqrt(ab))^n
    Yn = (sqrt(b)-sqrt(a))^2n = (b+a-2sqrt(ab))^n
    Zn = Xn +Yn = (b+a+2sqrt(ab))^n + (b+a-2sqrt(ab))^n
 
 由于X1 = b+a+2sqrt(ab) , Y1 = b+a-2sqrt(ab)
 是方程(U-X1)(U-Y1) = 0 ,即 U^2 - 2(a+b)U + (a-b)^2 = 0 的根
 則Zn+2 = 2(a+b)Zn+1 - (a-b)^2Zn
 用矩陣乘法可以求得Zn
 由于Yn<1 ,所以floor(Xn) = Zn - 1,所以最后答案Zn-1即可

 以上方法有個地方
 “
 由于X1 = b+a+2sqrt(ab) , Y1 = b+a-2sqrt(ab)
 是方程(U-X1)(U-Y1) = 0 ,即 U^2 - 2(a+b)U + (a-b)^2 = 0 的根
 則Zn+2 = 2(a+b)Zn+1 - (a-b)^2Zn
 ”
 我不太懂,查了下特征根的一點東西
 若An+2 = pAn+1 +qAn
 則An = C1α^n + C2β^n
 上面應該是逆過來
 由Zn = Xn +Yn = (b+a+2sqrt(ab))^n + (b+a-2sqrt(ab))^n
 推出Zn+2 = 2(a+b)Zn+1 - (a-b)^2Zn
*/


zoj 3461
/*
 給出一個無向圖,有邊權,點權。點權val[i]為正的表示要將val[i]分出給點權為負的,每個點可以作為中間節點
 點權val[i]為負的表示要接收val[i],傳送的花費為路徑的距離,求最小距離
 n<=16

 按照題意,花費即為∑val[i] = 0 的樹的MST 
 我有想過需要劃分成幾部分,起初沒想過怎么劃分

 解題報告是枚舉子集作為一部分樹,dp求解(n那么小,要往集合方面想吧?。?br> 即dp[mask] = dp[mask^i] + mst[i];
 注意需要sum[mask] = 0 的才有意義
*/


zoj 3463
/*
 一只手,相對拇指不動,至少要占5個鍵的位置,至多可以彈到9個鍵。
 拇指移動距離x需要花費floor(sqrt(x)),已知左右手初始位置和接下來
 需要彈奏的1000個鍵,求最小花費。

 狀態比較明顯,dp[n,l,r]表示已經彈了n個音符,左、右手拇指分別在l,r
 的最小代價
 無效狀態很多,不能計算,否則會超時
 枚舉左右手到需要彈的位置,其他情況不用考慮,不會更優

 這句話不太懂:"But, one finger touching the key between two fingers of the other hand is fobidden."
 貌似不用處理?
 
 看watashi的代碼的
 sqrt的初始化很漂亮

 hdu 3651是簡化版,都是無效狀態不用算,決策是直接到需要的位置
*/


zoj 3464
/*
 N個人,起初在一條線上。
 每個人有速度vi,且每個人最多只能跑帶著棒Ts,問最快時間接棒跑完L

 貪心,最快的人跑最后Ts,倒數第二快的跑倒數第二Ts...
*/



TCO'10 Wildcard Round 500pt CalculationCards
/*
 n<=50張卡 如3張:+1 ,-2 , *3  其排列有
 0 + 1 - 2 * 3 = -5
 0 + 1 * 3 - 2 = 1
 0 - 2 + 1 * 3 = 1
 0 - 2 * 3 + 1 = -5
 0 * 3 + 1 - 2 = -1
 0 * 3 - 2 + 1 = -1
 期望為-1.6666666666666667
 求給定的n張卡的期望值

 看解題報告
 以及bmerry代碼的

 不可能n!的枚舉
 設+、-卡共有s張
 按照一個+、-卡后接連續的*卡分類,則有s部分,其全排列不影響期望(總共s!種,但期望都一樣)
 所以只考慮無序的(無序可以用默認的一種順序,即卡出現的先后順序,或者說編號)
 ***a1***a2*** ... as***
 ***表示*卡
 由于是等概率的,所以總體來統計,每個+、-卡都會接同樣的*卡,
 既然每張+、-卡情況一樣,那就考慮a1卡
 其后會接0,1...,m張*卡
 答案就是 sum * (0,1,...m)張*卡的期望   sum = ∑ai
 求k張*卡的期望可以用dp做
 看bmerry代碼的做法,解題報告的麻煩一點吧
 一開始只有s張a卡排著,然后插入一張張*卡
 dp[i,j]表示插入了前面i張*卡,a1后接j張*卡,它們構成的期望值
 分第i張卡插不插入到a1之后構成j張連續的*卡,概率為 該插入的位置/總位置
 dp[i,j] =
    dp[i-1,j] * (n-j-1)/n
   + m[i]*dp[i-1,j-1] * j/n
 n為s+i

 這道題一個很好的想法就是答案為sum * (0,1,...m)張*卡的期望   sum = ∑ai   !?。。。?!
 而求后接k張*卡的期望,bmerry的做法是一張一張卡插入,然后求得期望
 小規模到大規模,通過考慮插入位置來實現,這個做法應該較好
*/


TCO 2010 Qualification Round 1 250pt
/*
 題意:一個只有B,G組成的串,要將他們swap相鄰的,變成BB...GG或GG...BB
 求最少的次數  串長<=50
 我用n^2的求逆序對,太慢了
 看了別人的,直接就是累計將每個字母B移到左邊的步數
 if(row[i] == 'B')
 {
  tot += i - x;
  x ++;
 }
 x是當前需要放B的位置,交換后就++移到下個位置
*/



TCO'10 Qualification Round 2 1000pt HandlesSpelling
/*
 給出一個文本串,一些模式串
 現要將模式串覆蓋文本串,不能有重疊部分
 求使得A^2 - B 最大
 A是最長覆蓋的長度,B是還未覆蓋的個數

 一開始一直關注A^2 - B ,不知怎么做
 解題報告是分開來做
 要求得A^2 - B的最大值,可以通過枚舉A
 枚舉某一段作為最大覆蓋值,然后看其左右未覆蓋的個數

 而計算為覆蓋的個數可以通過dp了
 dp[i,j]表示[i,j]為覆蓋的個數
 枚舉[i,i']一段是被覆蓋的,則答案就是min(dp[i'+1,j])
 注意的是,初始化有些dp[i,j]=0,就直接continue
*/


SRM 216 Refactoring
/*
 問一個數n<=2*10^9 可以拆分成多少種因子相乘的情況
 24 = 2*2*2*3
   = 2*2*6
   = 2*3*4
   = 2*12
   = 3*8
   = 4*6
 
 不需要高深的數學知識?。。?br> 暴力dfs做
 f(n) = 1 + ∑f(n/i) 
 i 為其因子,i > 1 && i <= n/i(保證不會進入多余的分支)
 為了保證無序,可以多加一個參數start,表示該輪的因子>=start
*/



SRM 223 PrimeAnagrams
/*
 給出一個數字串len<=8
 求將其分為三部分,每部分都是素數,且乘積最小

 看解題報告的
 8! = 40320 ,而分成3部分情況為C(7,2) = 21種
 所以枚舉全排列,然后分成3部分來做

 Brute Force !?。。。。?br>*/


zoj 3471 mask dp
/*
 n<=10個球,i碰j會產生a[i,j]的能量,j同時會消失
 問最多產生的能量之和
 
 我知道跟mask有關,為啥還是想不出?
 
 要從整體來看??!
 現在有一些球,掩碼為mask
 假設最先碰撞的是u->v,然后v消失了
 局面就變成了沒有v的一些球了, mask^(1<<v),一個子問題了
 所以轉移就是枚舉u,v
 dp[mask] = max(dp[mask^(1<<v)+a[u][v]) 

 從局面來看吧?。?!

 一開始我是像zoj 3461 dp[mask] = dp[mask^i] + mst[i];
 發現會出問題,這樣子是隔離了一部分,但顯然隔離了后會丟失了連接著兩部分的那個值
 
*/

 



zoj 3470
/*
 如圖,問某個數字上下左右的數字是多少
 既然題目給了一副對應的坐標,發現,問題的重點就在于點坐標跟數字的轉換
 
 我是先找出數字val在第n圈 即 (n-1)^2 < val <= n^2
 然后該圈的起點start就是(n-1)^2 + 1 , 然后通過比較start,就能求出坐標了
 發現奇數圈會使minx--,miny-- ; 偶數圈會使maxx++,maxy++
 數量關系是minx = miny = -(n-1)/2 , maxx = maxy = n/2
 
 然后點(x,y)轉化為值,跟上面類似的
 求出第n圈  二分判斷 minx<=x<=maxx , miny<=y<=maxy
 然后求出角落的點等等...
*/


zoj 3468
/*
 Dice游戲,一開始Attacker Defender各有骰子n,m個
 雙方拿出一定骰子來投,累計和
 誰多點誰贏
 Attacker拿出至少1個來攻擊
 問Attacker一次攻擊贏的概率
 骰子數目<=8
 枚舉Attacker投出的和為j,然后計算達到j的方法數,以及Defender投出的和小于j的方法數
 
 用背包的方法計算方法數
*/

CF 60D
/*
 n<=10^6個點,每個點有權值a[i]<=10^7 各不相同
 若存在一個數x,使得a[i],a[j],x   is a beautiful triple
 即a^2 + b^2 = c^2   a,b,c互素
 則i可以傳播laugh到j
 問最少需要需要讓多少個頂點自行laugh,然后傳播到全部的頂點

 看了解題報告的
 并查集做
 但如何判斷beautiful triple 兩兩判斷O(n^2)會超時

 有個性質:對于滿足a^2 + b^2 = c^2的數,可用勾股數公式生成:
 (x^2-y^2 , 2xy , x^2+y^2)  x>y
 該公式能生成所有的素勾股數(互質),需1奇1偶 ,且gcd(x,y) = 1
 也能生出部分派生勾股數(如 6 8 10) , 2奇或2偶
 
 由于a[i]<=MAX       MAX= 10^7
 所以必有x^2-y^2 <= MAX , 2xy <= MAX  但x^2+y^2不一定<= MAX
 2y^2<=MAX
 x^2<=MAX+y^2<=3MAX/2
 => x<=sqrt(3MAX/2) , y <= sqrt(MAX/2)
 所以枚舉x,y復雜度為O(MAX)
 (注意x,y是1奇1偶且gcd(x,y) = 1)

 參考watashi代碼寫的 
*/


CF60E
/*
 一開始 n <= 10^6 個 Mushroom 按升序排成一條直線 , 每個Mushroom重為a[i]
 下一秒時,a[i] , a[i+1] 之間會出現一個a[i]+a[i+1]的Mushroom
 而x秒時,某人重新排序這些Mushroom
 問再經過y秒,所有Mushroom的重量之和

 0 a1  a2  a3
 1 a1  a1+a2  a2  a2+a3  a3
 2 a1  2a1+a2  a1+a2  a1+2a2  a2  2a2+a3  a2+a3  a2+2a3  a3
 3 ...
 設時間i時重量為Ti 則Ti = 3Ti-1 - (a1+an)
 所以前x可用矩陣乘法求出Tx
 然后由于sort,最大的值是Fx-1*an-1 + Fx*an (找規律 Fx-1*ai-1 + Fx*ai , Fx*ai-1 + Fx-1*ai)
 F是斐波那契數列  F[-1] = 0 , F[0] = 1
 然后修改a1+an值即可,再次矩陣乘法 算出后來的y秒
*/


noip2002 G2 字串變換 雙向BFS
/*
 給出A,B串
 以及一些變化方法,即x->y
 求A變到B的最短步數
 
 bfs慢點
 雙向會快點
 由于x->y是單向的,所以兩邊的結構不同,優先擴展隊列長度短的優化就有用了
 注意反向BFS時擴展的順序是y->x
*/

poj 2411
/*
 問n*m的棋盤放置1*2的骨牌的方案數
 n,m<=11
 
 枚舉行,遞推計算列
 dp[row,col,s]  row行之前已經放好,且當前row行處于s狀態
 遞推 通過在row行,col列之后放置,擴展計算
 dp[row,col,s1] += dp[row-1,col,s2]

 不是記憶化搜索 是從0遞推
 為了打表,在每個分支都計算了  即:dp[row][col][s1] += dp[row-1][col][s2];
 否則,可以在最后的時候才計算的
*/

sgu 131
/*
 n*m棋盤,問用1*2, 2*2去掉一個角的骨牌覆蓋完的方案數
 
 狀態定義為 dp[row,s]表示當前第row行狀態為s,且前row-1行已經覆蓋完的方案數
 則 dp[row,s] <-- dp[row-1,s']
 轉移是枚舉row這一行每個位置(注意是整行)怎么放
 同時,若枚舉了row怎么放,則由狀態的定義,row-1之前的必須覆蓋完,就知道了s'是什么了!!!
 
 每個位置有7種放法,除了被之前的方法限制了,就不足
*/


hdu 2640
/*
 n*m的棋盤,有一些位置不能放,問最多能放多少個十字架
    @
 @@@
    @

 注意的是,每個@都需要放,所以棋盤相應的位置需要是空的
*/


xmu 1118
/*
 求用1*1,1*2,1*3的磚塊鋪滿 3*N的板的方案數目
 1*3,最多影響3行 所以狀態需要記錄當前行以及前一行的情況  2bit 共4種
 _    *    _    *
 _    _    *    *
 _表示空,*表示被覆蓋

 dp[row,s]表示row-1之前的已經覆蓋完了,row-1,row的狀態為s時的值
 
 對row這一行的每個位置,枚舉其放的方法
 雖然說4種狀態,實際上轉移時很多是不需要的。因為為了滿足row-1之前的是覆蓋完的

不放,可以轉移兩種,即上面的1,2種類型
*/



hdu 2240
/*
 給出如圖n*5棋盤,其中第一塊最多只能用c個,其余的不限
 問能否鋪滿
 跟sgu 131類似
 不過這里dp的值是記錄最少使用的1
 b1,b2是之前的方法對當前的影響
*/



hdu 2606
/*
 用1*1, 2*2, 3*3, 4*4覆蓋完N*4的棋盤的方案總數
 遞推
 dp[n] =  dp[n-1]         最底部放4個1*1
           + 4*dp[n-2]     最底部組合出2*4的,總共有4種
           + 4*dp[n-3]     最底部組合出3*4的,總共有4種  2個是2塊2*2上下交錯 2個是一塊3*3
           + 3*dp[n-4]     最底部組合出4*4的,總共有3種  2個是3塊2*2上下交錯 1個是一塊4*4
    + 2*(dp[n-5]+dp[n-6]...+dp[0])    用2*2上下交錯放的
 則dp[n-1] = ....
 兩式相減,得到dp[n] = 2dp[n-1] +3dp[n-2] - dp[n-4] - dp[n-5]    n>=5
 至于n<=4的,結合上面的dp[n]的式子計算

 腦殘了,wa了好幾次
 沒想到可以2*2上下交錯  腦殘
*/



hnu 10816 ugly number
/*
 題意:給出n個素數<=10000  n<=10
 問[x,y]區間內只包含這些素數因子的數,要求全部打印出來
 x,y<=2^31
 一開始看到規模嚇了一跳
 事實上,只含有這些因子的數是很少的
 注意不是倍數?。≈暗谝挥∠罂闯杀稊?,搞個容斥了,算了下2和3的,數據巨大....
 
 像poj 的 ugly number那樣子做
 由于每個數都得乘以這些素數來擴展
 用num[]數組存儲生成的所有數
 pos[i]表示素數pr[i]當前要乘以num[pos[i]]
 初始num[0] = 1  pos[i] = 0
 然后每一步擴展一個數,該數為num[tot] = min(num[pos[i]]*pr[i])
 然后判斷每個num[pos[i]]*pr[i] 是否 = num[tot],是的話 pos[i]+1
 
 這種思想還是沒能很好掌握...
 肯定的是,每個數都得乘以pr[1],pr[2]...
 要用pos[i]記錄當前pr[i]乘到哪個數了!?。?br>*/



08 ZhuHai Contest  E Magic Squares 雙向bf
/*
 問一個排列變為3*3幻方的最小步數
 每一步可以選擇一個角進行旋轉
 
 狀態數不多9!
 先全排列得到目標狀態
 再雙向bfs  挺快的
 用康托展開(變進制)判重更快
*/


poj 3255 無向圖值次短路 ★★★
/*
 給出一個無向圖 n<=5000, m <= 30000
 求1到n的值次短的路,如果有多條最短路,但次短的還是需要大于最短的
 允許點、邊走多次

 靠解題報告保養~~~ T_T
 求1到其他點的最短路dist[] ,再求n到其他點的最短路rdist[]
 枚舉每條邊,找到次短的 dist[u] + (u,v) + rdist[v]

 啟示:  枚舉哪條邊作為中間的必須經過的邊u->v,然后連接1->u, v->n
*/


scu 3904
/*
 一個序列seq[i]   n<=10^5                -10000<=seq[i]<=10000
 將其劃分成幾部分,使得每一部分之和>=0
 求所有的劃分方法數
 顯然dp[i] = ∑dp[j]   (sum[i] - sum[j] >= 0)
 O(n^2)會超時
 用線段樹加速
 我一開始是以下標作為線段樹的數軸,記錄該段Min[p],Max[p],還有一個sDp[p]記錄該段所有dp值
 但這樣比較慢,維護相對多了點

 看了標程,是先計算所有的sum[],然后離散化
 以sum值作為數軸來搞,用樹狀數組就很容易寫了

*/


中大第三本 ch2 負權數
/*
 平時 N = anR^n + ... + a0R^0  其中R>0
 負權數是R < 0,使用負權數表示的優點是對于負數,不用前置的符號
 比如 -15 = 1*(-2)^5 + 1*(-2)^4 + 0*(-2)^3 + 0*(-2)^2 + 0*(-2)^1 + 1*(-2)^0
 現給出N,  -16<= R <=-2
 求N的負權數R表示(題目的答案輸出一行,表明表示是唯一的)
 (無論正權、負權,系數ai都是 0<=ai<|R|)
 
 因為取余運算只使用語正整數除法,所以不能通過連續連除求余的方法?。。?!
 寫成普通形式時:

 N >= 0
 N = an|R|^n + ... + a0|R|^0 R < 0
 i為奇數時:
  ai|R|i = R(i+1) + (|R|-ai)Ri          為了保證a'>=0
 i為偶數
  ai|R|i = aiRi
 所以先將N寫成正權形式,然后再修改為負權的

 同理
 N < 0
 N = -(an|R|^n + ... + a0|R|^0) R < 0
 i為奇數時:
   -ai|R|i = aiRi         為了保證a'>=0
 i為偶數
  -ai|R|i = R(i+1) + (|R|-ai)Ri

 最后對a'[]進行修正,使得0 <= a'i < |R|


 感覺挺不錯的一道題,通過對正權的形式,修正為負權的
*/