1001

显然,题目给的是一个0/1规划模型。

解题的关键在于如何看出这个模型的本质。

3个条件明显在刻画未知数之间的关系,从图论的角度思考问题,容易得到下面3个结论:

1.X12+X13+...X1n=1  于是1号节点的出度为1

2..X1n+X2n+...Xn-1n=1 于是n号节点的入度为1

3.∑Xki =∑Xij  于是2~n-1号节点的入度必须等于出度

于是3个条件等价于一条从1号节点到n号节点的路径,故Xij=1表示需要经过边(i,j),代价为Cij。Xij=0表示不经过边(i,j)。注意到Cij非负且题目要求总代价最小,因此最优答案的路径一定可以对应一条简单路径。

最终,我们直接读入边权的邻接矩阵,跑一次1到n的最短路即可.

 

 

1002

结论:在所有的d中,选择最小的d,这里记作dmin,Alice和Bob每次都选择+dmin(写下的数是在原来的那个数上加上dmin),按照这样的策略最后的结果就是全局的结果。 

可以这样考虑正确性,不妨假设按照以上策略是Alice获胜,那么Alice并不会主动改变策略;假设Bob在某一步突然改变策略,即没有选择+dmin,那么就必然选择了某个+d(不会是-d,因为这样肯定不合法),且d > dmin,那么下一步Alice就可以选择-dmin了,再下一步,Bob就只能选择某个+d,且d > dmin,Alice则可以一如既往的选择-dmin,如此循环,无论每次Bob做什么样的决策,Alice都可以选择-dmin,所以肯定是Bob最先没有选择,同样是Alice获胜。这样就证明了开头的结论。   

 

 

 

1003 题目大意:有N个高楼,楼的高度为N的一个排列,现在从左到右能看到x个,从右往左能看到y个,问高楼一共有多少种排列。


方法一: 
设dp[i][j][k] 为共i个楼,从左往后看到共j个,从右往左看共k个的方案种数 
dp2[i][j] 为共i个楼,从左往右看共j个的方案种数 
则dp2[i][j] = sum(dp[i][j][]) 
枚举当前最高建筑物的位置,即将排列分为前后两半,分解为两个子问题 
dp[i][j][k] = sum( C(i-1,t)*dp2[t][i]*dp2[n-1-t][k] ) (0<=t<=i-1) 
其中C(n,m)为组合数 
复杂度O(n^4)。要超时。 

方法二: 
dp[n][x][y]表示一共n幢楼,从左数看到x幢,从右数看到y幢,则 
dp[n][x][y] = dp[n-1][x-1][y]+dp[n-1][x][y-1]+(n-2)*(dp[n-1][x][y])
就是枚举一下最低的楼的位置,最左,最右,和中间。 
复杂度 O(n^3) 。要超时。 

方法三: 
f[n][k] 表示单边看过去,共 n 幢楼,最高楼在另一端,看到了 k 幢的排列个数。于是 
f[n][k] = sigma(f[x][k - 1] * C[n - 2][x - 1] * (n - x - 1)!) 
= sigma(f[x][k - 1] * (n - 2)! / (x - 1)!) 
= f[n - 1][k] * (n - 2) + f[n - 1][k - 1] 
于是算答案就是 answer(n, x, y) = sigma(f[i][x] * f[n - i + 1][y] * C[n - 1][i - 1]) 。 
预处理 O(n^2),每组 case O(n)。不过还是要超时。 

方法四: 
n^3的算法暴力出后找规律可得dp[n][i][j] = dp[n][i - 1][j + 1] * j / (i - 1)。 
其中dp[n][1][i] = S1[n - 1][i - 1] 
进一步化简得到dp[n][i][j] = S1[n - 1][i + j - 2] * C[i + j - 2][i - 1] 

(i,j,k)=(i,j-1,k+1)*k/j-1 
(i,j,k)=(i,j-2,k+2)*k/j-1*k+1/j-2 

(i,j,k)=(i,j-3,k+3)*k/j-1*k+1/j-2*k+2/j-3 
=(i,1,k+(j-1))*k*k+1*..*k+(j-2)/j-1/j-2/.../1 
=S1[i-1][k+j-2]*fact[k+(j-2)]/fact[k-1]/fact[j-1] 
=S1[i-1][k+j-2]*C[k+(j-2)][k-1] 

直观意义上就是假设最高的建筑物位置固定,定义最高建筑物左边的某个建筑和它右边相邻的若干个比他小的连续的建筑物称为一组,右边的某个建筑和它左边相邻的若干个比他小的连续的建筑物也称为一组,每个组都有一个建筑物最高值。那么问题等价于,剩下N-1个建筑物,左边X-1个左到右值递增的组,右边Y-1个右到左值递增的组。首先考虑分组,可以发现问题就等价于n-1个人分成x-1+y-1组,每组内再按特定顺序围圈的分组方法的数目,即第一类斯特灵数的S1[n-1][x+y-2],因为每一个环排列都有它的一个最大表示法,最大表示法的第一个元素就可以代表该组的最大值。然后第二部是左边分X-1个,右边分Y-1个,即乘上组合数C[x+y-2][x-1],即得到答案。 
预处理 O(n^2),每组 case O(1)。 

 

 

 

1004 本题为中等组合数学/数论题。 
首先观察全是12222……这种形态的for结构。 
也就是如下结构: 
for (int i = 0; i < n; i++) { 
for (int j = i; j < n; j++) { 
for (int k = j; k < n; k++) { 
…… 
} 
} 
} 
这样的是平时写程序经常用到的一种循环结构,这个简化的问题等价于n种不同颜色的球,可放回地取m个,问形成最后的结果集合不同的种类数。 
为什么等价呢?因为由于是集合,我们可以用排序后的数列来表示一个集合,那么对于每个取球方案都可以对应到一个数列,如: 
3种不同颜色的球,可放回地取3个,共有111,112,113,122,123,133,222,223,233,333这10种不同的方案,显然因为方案是有序的,所以他们跟简化题意是可以一一对应的,比如223就对应a[0]=2,a[1]=2,a[2]=3的一种合法方案。 
那么现在问题就是求这个简化问题的公式了,有很多方法可以求这个公式,这里介绍一下我的做法:首先列n+m个空位,现在我们固定最右边的空位里放的是第n种颜色的球,现在我们只要在剩下的n+m-1个位置里放入n-1个球,然后从左到右标记为1~n-1种颜色,即能得到一种方案,这个方案里每种颜色的球取的个数为它左边的连续的空位数。比如我们还是取n=m=3为例,列6个空位:oooooo,最右边填上颜色3:ooooo3,现在在剩下的空位里放入颜色1,2的球,比如有方案:o12oo3,则表示1取了1个,2取了0个,3取了2个,也就是对应133这种方案。至于为什么最右边要填第n种颜色的球是因为我们要现在令的是每个球左边连续的空位数是它对应取的个数,所以最右边的球右边不能有空位,故位置固定。所以现在问题就十分简单了,公式为C(n+m-1,n-1)=C(n+m-1,m)。 

接下来搞的是一般结构,由于一共有最多15个1-type的for-loop,所以只要每个以1type开头后面跟若干2type形成的组合结构单独处理,15个组合结构答案相乘即可,因为每个1-type重新开头后答案跟之前都是独立的。 

最后的问题就是如何计算C(n+m-1,m)%MOD,其中0<=n+m-1<=1100000,0<=m<=100000,MOD是两个质数的乘积:97*3761599。 
这里我的方法是处理任意MOD数的问题,由于上限是1000000,求出在1000000里面约有15w个质数,因为幂项相除等于指数相减,对于每个组合数我们算得它分解后的质数里面每一项的幂v,对于分子我们将幂+=v,对于组合数分母的两项,我们将幂-=v,所以一共最多15w项质数,最后就没有乘法了,可以二分快速幂取模得到答案。首先筛法得到质数后,每组Case计算量约为15w*15*log(n+m-1)。即可得到答案。 
另一个更好的方法是用Lucas定理,由于364875103=97*3761599,于是我们可以分别对这两个质数进行组合数的计算 ,然后用中国剩余定理求出对于 MOD 的余数,Lucas的每次计算组合数的复杂度大概是 O(log n * log p),于是每 组Case计算量大概是15 * log n * log p。    

 

 

 

1005 dp[i][j] = dp[i-1][k] + dis(k,j); 

dp[i][j] = dp[i-1][1] + dis(1,j); 
dp[i][j] = dp[i-1][2] + dis(2,j); 
... 
转换为 
dp[i][j] = dp[i-1][1] + dis(1,j); 
dp[i][j] = dp[i-1][1] + dis(2,j)+[dis(2,j)-dis(1,j)]; 
... 
这样只要比较dis(1,j)和dis(2,j)+[dis(2,j)-dis(1,j)] ... 
在距离限制内维护一个单调队列可以O(1)取到最值  

 

 

  1006 首先,这题如果用 1000 * 1000 * 4 * 1000000 的暴力方法,肯定是不行的。 
那么我们在观察了这个 LR 序列后发现,其实每一个指令,其朝向是一定的,进而,对于每个 (x, y, direction) 状态来说,一定有多个指令位置可以达到,而对于我们来说,贪心得找到最小的指令位置就可以了。于是就要把下一个方向的指令位置预处理出来,如果 bfs 的时候暴力找,仍然是要 TLE 的。于是对于四个方向来说,bfs 的时候就需要使用优先队列,这个地方,标程的处理是使用 N + 1 个链表,将时间降到 O(1) 。最后总复杂度在 1000 * 1000 * 4 * 4 + 1000000 * 4 这样。    

 

 

 

1007

简单自动机结合数位DP。首先对需要包含的第一个子串与反转后的第二个子串跑自动机。然后进行数位DP。此题不满足区间相减性质。所以要将反转前与上下界的比较情况,翻转后与上下界的比较情况都记在状态中。dp[l][sa][sb][rsa][rsb][u][mask]表示长度为l,和a的前l位比较结果为sa,和b的前l位比较结果为sb,反转后的串和a的前l位比较结果为rsa,反转后的串和b的前l位比较结果为rsb,处在自动机上的第u号节点,包含两个子串的状态为mask的情况的方案树。最后进行简单统计即可。

 

 

1008

其实这是个挺有趣的题,你需要构造一个 1..N 的排列,使得其最长上升序列的长度和最长下降序列的长度的最大值最小。应该比较容易能够想到这个答案是 sqrt(N) 级别的,这个结论的证明可以参考吴文虎的那本组合数学 p21 。 
当然这还没有结束,怎么找字典序最小的那个解呢?先看看完全平方数吧,对于 4 ,我们有 2 1 4 3 ,对于 9 ,我们有 3 2 1 6 5 4 9 8 7 。嗯,完全平方数的规律还是好找的,那么 5 呢?不就是加一个数么,1 3 2 5 4 ,如果你觉得这是答案,那你就大错特错了,答案是 1 2 5 4 3 。同样,对于 10 ,答案是 1 2 6 5 4 3 10 9 8 7 。 
于是我们就可以构造程序,每次以 ceil(sqrt(N)) 为一组,尽量把大的数安排到后面的组中,同时要注意,一定要分出 ceil(sqrt(N)) 组,能让较小的 1 2 这样的数能够排在前面。 
最后,这题并不难,但是做到 1Y 也不容易,这就要克服各种逻辑上的问题,形成良好的思维习惯,对于解题来说也是十分重要的。

 

 

 

   

1009

题目大意:在一个球上由两点确定一个圆环,这个圆环上的点到两点的距离相同。而军队在球上另一点,现在军队要走到球面上距离圆环最远的点,问所需最短时间。

由于题目中给定的点都是用经纬度确定的,所以首先要将球坐标转换为空间笛卡尔坐标。观察到确定圆环的两个点所构成的向量正是圆环所在平面的法向量。

 

 

1010

简单题,首先想到所有小于 L/2 的,统统可以放进来,最后,按照题意,还可能可以放一个大于 L/2 的数进来,当小于 L/2 的数里面的最大值加上这个大于 L/2 的数的和小于 L 时,答案加一。最后要注意所有数都小于 L/2 的处理。O(n) 算法可过此题。

posted on 2012-08-16 19:43  pony1993  阅读(298)  评论(0编辑  收藏  举报

View My Stats