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 而已,脑残了!!!
因为(a^n - b^n) % (a-b) = 0
可以几位合在再mod会快点
最后结果要不断加上10-x,使得逼近于10
*/
zoj 3450
/*
一个定点p0,n个目标点 ,每个目标点有敌人wi,要消灭该点需要ti时间
弱目标点在同一直线,必须先消灭近的才能消灭远的
问在T时间内最多能消除的敌人
分组背包
注意的是,坐标比较大,用double会精度不够
看了watashi的做法
他将坐标都除以他们的gcd ,相等的就是同一直线了,而gcd就用来判断距离了!!
这样将大数变小了!!!
注意的是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)。问平均路长
参见解题报告:http://www.codeforces.com/blog/entry/1171
题目的那种规定,发现,对于同一行、列,如果要跨过那个'X',就需要多加2
而对于连续行的'X',如下图:
1..X.....
2....X...
3......X.
1的左边到1、2、3的右边需要多加2
2的左边到2、3的右边也需要多加2
...
另外,对于下图:
1..X.....
2......X.
3....X...
1的左边到2的右边需多加2,而到3的右边不需加
2的右边到3的左边需多加2
所以,从上往下,对于连续的行,寻找递增或递减的一块,然后对于这一连续的块,统计从左边到右边
或右边到左边需要多加的步数2
解题报告的框架,两两点距离之和(包括'X')- 'X'到所有点距离和*2 + 'X'到'X'距离和*2
这里多减了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那么小,要往集合方面想吧!)
即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张卡的期望值
看解题报告http://www.topcoder.com/wiki/display/tc/TCO'10+Wildcard+Round
以及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
不需要高深的数学知识!!!
暴力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 !!!!!!
*/
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]乘到哪个数了!!!
*/
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|
感觉挺不错的一道题,通过对正权的形式,修正为负权的
*/