<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Together: Find&#039;s Blog &#187; 算法相关</title>
	<atom:link href="http://kmp.cc/blog/archives/category/report/feed" rel="self" type="application/rss+xml" />
	<link>http://kmp.cc/blog</link>
	<description>Be the one we wanna be</description>
	<lastBuildDate>Sat, 12 Jun 2010 19:47:12 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>关于群论的一些东西</title>
		<link>http://kmp.cc/blog/archives/491</link>
		<comments>http://kmp.cc/blog/archives/491#comments</comments>
		<pubDate>Sat, 21 Mar 2009 10:26:52 +0000</pubDate>
		<dc:creator>Find</dc:creator>
				<category><![CDATA[算法相关]]></category>
		<category><![CDATA[Pólya原理]]></category>
		<category><![CDATA[sgu]]></category>
		<category><![CDATA[群论]]></category>

		<guid isPermaLink="false">http://dqfind.com/blog/?p=491</guid>
		<description><![CDATA[尽管Pólya是一个很偏的东西, 但还是花了两三天的时间大概的学了一下, 搞了两道sgu上的题. 因为没有系统的学, 所以很多东西还是了解的不透彻.
sgu282 Isomorphism
 一道用来实践Pólya原理的好题. 给一个有n个结点的完全图, 求用m种颜色染色的不同方案, 重新排列点的序号后重合的方案算一种.
这道题可以很容易看出需要用Pólya原理, 但是不同的置换方案超过52!(每一种点的置换方案唯一的对应一种边的置换方案). 于是我们需要将点置换分类别, 将置换按循环节长度排序, 如(1)(234)(5678)就是一种&#8221;格式&#8221;为 1-3-4 置换方案, 如果一种置换表示为 s1-s2-s3-&#8230;-sk, 显然 s1+s2+s3+&#8230;+sk=n. 于是这是n的一个划分. 通过搜索我们知道53的划分并不多. 当有了一个特定的置换&#8221;格式&#8221;, 我们可以很容易的用组合数学知识算出有多少种对应的点置换, 对于&#8221;格式&#8221; s1-s2-s3-&#8230;-sk, 有 n!/(s1!*s2!*s3!*&#8230;*sk!)/(t1*t2*&#8230;*tr) * (s1-1)!*(s2-1)!*(s3-1)!*&#8230;*(sk-1)! = n!/(s1*s2*s3*&#8230;*sk)/(t1*t2*&#8230;*tr) 种, 其中t1, t2, &#8230;, tr是相邻重复的sk的个数, 如 1-3-3-4-5-5-5-6 就有 t=(1,2,1,3,1). 由于对Pólya原理的理解不对, 我到这儿以为只要将点置换的个数及循环节数套进公式就可以了, 但这是错的, 回想Pólya原理的证明, 它的证明是建立在Burnside定理基础上的, Burnside定理中对象是不同的染色方案, 染色方案是针对边的, 所以在Pólya原理中置换群中的对象也必须是边 (而不是点).

下一个问题是如何通过一个点置换求出它相对应的边置换的循环节数. 可以证明:
 1) 一个长度为 s 的点置换循环节对应 [...]]]></description>
			<content:encoded><![CDATA[<p>尽管Pólya是一个很偏的东西, 但还是花了两三天的时间大概的学了一下, 搞了两道sgu上的题. 因为没有系统的学, 所以很多东西还是了解的不透彻.</p>
<p><em>sgu282 Isomorphism</em><br />
 一道用来实践Pólya原理的好题. 给一个有n个结点的完全图, 求用m种颜色染色的不同方案, 重新排列点的序号后重合的方案算一种.</p>
<p>这道题可以很容易看出需要用Pólya原理, 但是不同的置换方案超过52!(每一种点的置换方案唯一的对应一种边的置换方案). 于是我们需要将点置换分类别, 将置换按循环节长度排序, 如(1)(234)(5678)就是一种&#8221;格式&#8221;为 1-3-4 置换方案, 如果一种置换表示为 s1-s2-s3-&#8230;-sk, 显然 s1+s2+s3+&#8230;+sk=n. 于是这是n的一个划分. 通过搜索我们知道53的划分并不多. 当有了一个特定的置换&#8221;格式&#8221;, 我们可以很容易的用组合数学知识算出有多少种对应的点置换, 对于&#8221;格式&#8221; s1-s2-s3-&#8230;-sk, 有 n!/(s1!*s2!*s3!*&#8230;*sk!)/(t1*t2*&#8230;*tr) * (s1-1)!*(s2-1)!*(s3-1)!*&#8230;*(sk-1)! = n!/(s1*s2*s3*&#8230;*sk)/(t1*t2*&#8230;*tr) 种, 其中t1, t2, &#8230;, tr是相邻重复的sk的个数, 如 1-3-3-4-5-5-5-6 就有 t=(1,2,1,3,1). 由于对Pólya原理的理解不对, 我到这儿以为只要将点置换的个数及循环节数套进公式就可以了, 但这是错的, 回想Pólya原理的证明, 它的证明是建立在Burnside定理基础上的, Burnside定理中对象是不同的染色方案, 染色方案是针对边的, 所以在Pólya原理中置换群中的对象也必须是边 (而不是点).</p>
<p><span id="more-491"></span></p>
<p>下一个问题是如何通过一个点置换求出它相对应的边置换的循环节数. 可以证明:<br />
 1) 一个长度为 s 的点置换循环节对应 [s/2] 个边置换循环节;<br />
 2)两个长度分别为 s 和 t 的点置换对应 gcd(s, t) 个边置换循环节.<br />
 前者的证明是抓住某一个点为顶点的边出现在边置换中的规律, 后者是根据每一个对应的边置换的长度都是 s 和 t 的最小公倍数证明, 在这儿就不细写了.</p>
<p>还有一个问题, 在模运算中除法是很难做的, 但是在这道题的计算中除法模运算相当的多. 因为 p 是一个大于 n 的素数, 我们可以证明数 a 除以一个数 c 和乘以 c^(p-2) 取模 p 同余, 简证如下:</p>
<p style="padding-left: 30px;">a * c^(p-2) = a * c^(-1) * c^(p-1)<br />
 根据费马小定理, c^(p-1) mod p = 1, 所以 a * c^(p-2) 与 a * c^(-1) 取模p同余.</p>
<p>到这里这个问题就解决了, 将方案数和每个方案的循环节数算出来直接套Pólya原理的公式就可以了, 尽可能多的预处理出需要的数据.<em></em></p>
<p><em><br />
sgu139 Help Needed!</em><br />
 求15数码问题是否有解.</p>
<p>漫天飞的解题报告基本上就是两种解法, 记0到它应在的位置的曼哈顿距离为r, 一种将矩阵看作序列求出逆序对数x, 如果与r同奇偶则有解, 否则无解; 另一种是将每一个不在原位的数字与它原位的数字交换, 统计达到目标需做的交换次数y, 如果与r同奇偶则有解, 否则无解.</p>
<p>两种解法都要考虑 x/y 是否与 r 同奇偶, 我们可以联想到群论中的奇置换和偶置换. 考虑方法2, 它是从两个角度考察置换的奇偶性, 如果奇偶性不同, 显然无解 (奇置换不可能表示成偶置换), 方法1其实和方法2一样, 从某一个数开始按一定的规则与其相邻的数互换直到没有以它为其中一个元素的逆序对, 此时它的相对位置便是正确的, 接着再从当前情况的第一个存在逆序对的数开始做同样的操作, 直接序列中不存在逆序对, 这个在纸上画画也可以找到一定的规则. 到这里, 必要性容易得到, 但充分性呢? 我一直没有想出一个一定可以达到目标的置换方案, 求大牛指点.</p>
]]></content:encoded>
			<wfw:commentRss>http://kmp.cc/blog/archives/491/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>CEOI 2007 简明解题报告 (不完整)</title>
		<link>http://kmp.cc/blog/archives/469</link>
		<comments>http://kmp.cc/blog/archives/469#comments</comments>
		<pubDate>Tue, 03 Feb 2009 13:28:14 +0000</pubDate>
		<dc:creator>Find</dc:creator>
				<category><![CDATA[算法相关]]></category>
		<category><![CDATA[ceoi]]></category>
		<category><![CDATA[动态规划]]></category>
		<category><![CDATA[哈希表]]></category>
		<category><![CDATA[树型动规]]></category>
		<category><![CDATA[表达式]]></category>
		<category><![CDATA[解题报告]]></category>

		<guid isPermaLink="false">http://dqfind.com/blog/?p=469</guid>
		<description><![CDATA[Day I
 Ministry
 题目要求计算本质不同的树的形状. 我们可以给每一种不同的树给一个唯一的编号, 那么两棵树相同的充要条件是两棵树的树根有相同数目的孩子且孩子们的编号一一对应. 由于每个结点的孩子数很小(不超过三个), 我们可以从叶子到树根逐一枚举结点, 将三个孩子排个序, 按他们的编号求出一个Hash值, 并找之前有没有出现过相同的结点, 若没有, 则给这个结点分配一个新编号. 最后输出不同编号的个数即可.
Nasty
 尽管老师要求计算的值很多, 但是若最后一个数相同, 那么计算结果也将相同, 所以本质不同的x的值只有b个, 预处理一下就可以了.
Sail
 提交答案题, 不想做.. 以后再说.
 
 Day II
 Airport
 dp. 用 f[i][j] 表示第一个表现进行到第i步, 第二个表演进行到第j步可不可行, 若进行到 (i,j) 时没有哪个跑道被两场表演同时占据(这个可以在 (i,j-1) 的基础上维护), 且 f[i-1][j] 和 f[i][j-1] 中至少有一个为真, 则 f[i][j] 为真, 否则为假. 题目要我们求有没有 f[i][j]=true 且 f[i+1][j]=f[i][j+1]=false 的情况, 至于方案记录一下决策就好了.
Treasury
 用 g[i] 表示以 id=i [...]]]></description>
			<content:encoded><![CDATA[<p>Day I<br />
 Ministry<br />
 题目要求计算本质不同的树的形状. 我们可以给每一种不同的树给一个唯一的编号, 那么两棵树相同的充要条件是两棵树的树根有相同数目的孩子且孩子们的编号一一对应. 由于每个结点的孩子数很小(不超过三个), 我们可以从叶子到树根逐一枚举结点, 将三个孩子排个序, 按他们的编号求出一个Hash值, 并找之前有没有出现过相同的结点, 若没有, 则给这个结点分配一个新编号. 最后输出不同编号的个数即可.</p>
<p>Nasty<br />
 尽管老师要求计算的值很多, 但是若最后一个数相同, 那么计算结果也将相同, 所以本质不同的x的值只有b个, 预处理一下就可以了.</p>
<p>Sail<br />
 提交答案题, 不想做.. 以后再说.<br />
 <span id="more-469"></span><br />
 Day II<br />
 Airport<br />
 dp. 用 f[i][j] 表示第一个表现进行到第i步, 第二个表演进行到第j步可不可行, 若进行到 (i,j) 时没有哪个跑道被两场表演同时占据(这个可以在 (i,j-1) 的基础上维护), 且 f[i-1][j] 和 f[i][j-1] 中至少有一个为真, 则 f[i][j] 为真, 否则为假. 题目要我们求有没有 f[i][j]=true 且 f[i+1][j]=f[i][j+1]=false 的情况, 至于方案记录一下决策就好了.</p>
<p>Treasury<br />
 用 g[i] 表示以 id=i 的结点为根的树, 树根不与其孩子匹配的情况下的最大匹配个数, cg[i] 是这种情况下的方案总数; f[i] 表示以 id=i 的结点为根的树的最大匹配个数(树根可能匹配, 也不能不匹配), cf[i] 是这种情况下的方案总数. 则</p>
<p style="padding-left: 30px;">g[i]=sum( f[k] ), k是i的孩子<br />
 cg[i]=cf[k1]*cf[k2]*cf[k3]*&#8230;*cf[kn]<br />
 f[i]=max( g[i], sum( f[k] )+g[t]+1 ) = max( g[i], g[i]-f[t]+g[t]+1 ), t是当前枚举的i的孩子, k是其他孩子<br />
 cf[i]=sum(cf[k1]*cf[k2]*cf[k3]*&#8230;*cf[kn]*cg[t]) = sum( cg[i]/cf[t]*cg[t] )<br />
 另外, 当 g[i]=f[i] 时, cf[i] 还应加上cg[i]. 特别应注意 cf[i] 还应在有多解时用到加法原理.</p>
<p>Necklace<br />
 非传统题最近都不太想做..</p>
<p>照例附上题目, 数据和我的程序. <br />
 猛击<a href="http://dqfind.com/blog/wp-content/uploads/contest/ceoi2007.tar.gz" target="_blank">这里</a>下载.</p>
]]></content:encoded>
			<wfw:commentRss>http://kmp.cc/blog/archives/469/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Balkan 2007 简明解题报告</title>
		<link>http://kmp.cc/blog/archives/464</link>
		<comments>http://kmp.cc/blog/archives/464#comments</comments>
		<pubDate>Fri, 30 Jan 2009 13:03:28 +0000</pubDate>
		<dc:creator>Find</dc:creator>
				<category><![CDATA[算法相关]]></category>
		<category><![CDATA[balkan]]></category>
		<category><![CDATA[字母树]]></category>
		<category><![CDATA[线段树]]></category>
		<category><![CDATA[组合数学]]></category>
		<category><![CDATA[解题报告]]></category>
		<category><![CDATA[计算几何]]></category>
		<category><![CDATA[贪心]]></category>

		<guid isPermaLink="false">http://dqfind.com/blog/?p=464</guid>
		<description><![CDATA[Day I
 Cipher
 好像应该拿Hash做吧, 标程写的很离奇, 看不懂凭什么可以这么做. 自己也没能写出一个可以AC的程序.
Dream
 一道组合数学的题. 分析题目, 实际上是要我们从第一个盒子和最后一个盒子中取一个数, 其他盒子取两个数, 使乘积可以被k整除, 问有多少种方案. 
 首先求出k的所有因子集合S, 再为盒子中每一个数a在S中找到最大的数b使a mod b = 0. 这两个都需要预处理掉, 还有一个next[a][b]数组, 表示若一个数是k的第a和第b个因子的公倍数, 则它在S中最大的因子是第next[a][b]个因子. 之所以要最大, 在后面的运算中, 方案会优先累计到最大的因子, 即k本身上. 
 我们用total[a][b]表示到第a行为止, 累计到多少种方案可以使取数之乘积可以被k的被b个因子整除, 需要注意的是, 这里只是累计到的方案, 也就是实际的方案可能比累计到的多, 正如我们之前提到的, 如果某种方案所得到的乘积既能被第a个因子整除, 又能被第b个因子整除, 那么会优先记在记b个因子所表示的total单元中, 即较大的因子头上(假设b&#62;a). 我们先用累加的方法统计第一个盒子中的数字可以被哪个因子整除. 从第二行开始, 先统计单这一行得到的乘积可以被哪个因子整除, 之后再根据乘法原理计到total数组中去. 具体的说, 先用cur1表示只取一个数时可以被哪个因子整除(当然要尽可能大的因子), cur2表示取两个数后乘积可以被哪个因子整除(自然也要尽可能大的因子), cur1用与求第一个盒子相同的方法求出, 再枚举两个因子a,b, 若是相同的因子, 则cur2的next[a][b]单元(即乘积的最大因子)累加cur1[a]*(cur[a]-1) (乘法原理), 若不相同, 则cur2的next[a][b]单元累加cur1[a]*cur1[b]*2 (两种不同的取数顺序). 注意最后一行就不需要这样分两步统计了. [...]]]></description>
			<content:encoded><![CDATA[<p>Day I<br />
 Cipher<br />
 好像应该拿Hash做吧, 标程写的很离奇, 看不懂凭什么可以这么做. 自己也没能写出一个可以AC的程序.</p>
<p>Dream<br />
 一道组合数学的题. 分析题目, 实际上是要我们从第一个盒子和最后一个盒子中取一个数, 其他盒子取两个数, 使乘积可以被k整除, 问有多少种方案. <br />
 首先求出k的所有因子集合S, 再为盒子中每一个数a在S中找到最大的数b使a mod b = 0. 这两个都需要预处理掉, 还有一个next[a][b]数组, 表示若一个数是k的第a和第b个因子的公倍数, 则它在S中最大的因子是第next[a][b]个因子. 之所以要最大, 在后面的运算中, 方案会优先累计到最大的因子, 即k本身上. <br />
 我们用total[a][b]表示到第a行为止, 累计到多少种方案可以使取数之乘积可以被k的被b个因子整除, 需要注意的是, 这里只是累计到的方案, 也就是实际的方案可能比累计到的多, 正如我们之前提到的, 如果某种方案所得到的乘积既能被第a个因子整除, 又能被第b个因子整除, 那么会优先记在记b个因子所表示的total单元中, 即较大的因子头上(假设b&gt;a). 我们先用累加的方法统计第一个盒子中的数字可以被哪个因子整除. 从第二行开始, 先统计单这一行得到的乘积可以被哪个因子整除, 之后再根据乘法原理计到total数组中去. 具体的说, 先用cur1表示只取一个数时可以被哪个因子整除(当然要尽可能大的因子), cur2表示取两个数后乘积可以被哪个因子整除(自然也要尽可能大的因子), cur1用与求第一个盒子相同的方法求出, 再枚举两个因子a,b, 若是相同的因子, 则cur2的next[a][b]单元(即乘积的最大因子)累加cur1[a]*(cur[a]-1) (乘法原理), 若不相同, 则cur2的next[a][b]单元累加cur1[a]*cur1[b]*2 (两种不同的取数顺序). 注意最后一行就不需要这样分两步统计了. 然后再用类似的方法将统计结果累加入total数组中就可以了(再具体的见代码吧). <br />
 我的代码写的比较丑, 官方解答写的很漂亮, 看一下就明白了.</p>
<p><span id="more-464"></span></p>
<p>Points<br />
 如果三个点共线, 那么它们的向量也必然共线. 我们可以以一个点为标准求出所有到其他点的向量, 然后将这些向量转换成同方向的x=1的向量 ( 如果x=0, 则让y=1, 以此类推 ), 这样如果两个方向相同, 那么它们的(x,y,z)一定相等. 我们只在这条直线最侧端的点上计数这条直线, 也就是说, 如果存在从点A, B, C使AB=-AC, 那么我们不在点A处计这条直线, 否则只要存在两个以上的向量相等, 那么计数器累加1. 这样每条直线会被累加两次, 最后答案除以2就可以了. 寻找相反向量的过程可以用二分查找. 时间复杂度 O( n^2logn ).</p>
<p>Day II<br />
 Mokia<br />
 线段树就搞定了. 据说可以用后缀数组做, 但我不会二维的.. 不可以一下就把所有结点建好, 用一个建一个.</p>
<p>Stairway<br />
 比较让人头疼的贪心题. 策略是这样的: 建立一个表, 每次读数一个数字C, 将它插入最一行最后一个位置, 并保证第一行仍是非递减的. 如果不能保证, 则用二分查找找到不比C小的最小的数字, 用C替换它, 并把它插入到第二行的末尾去. 如果被踢到第二行的数字不能满足第二行非递送, 就按第一行的策略把另一个数字踢到第三行去, 以此类推. 最后表中第一行的数字个数就是一个不下降序列的最大长度, 前两行的总个数是两个不下降序列的最大长度, 以此类推.<br />
 证明这个策略的正确性有点麻烦. 需要证明两点: 策略产生的是最优值; 通过合理的排序前n行可以组成n个不下降序列. 前者的证明大概是证明这种策略不会让结果更差, 后者的排列方法是从新插入数字处断开, 连到上一行新插入数字之前输出.</p>
<p>Toponyms<br />
 用树做就可以了. 把每一个字母作为结点, 并记录匹配的单词个数, 做法很像USACO DEC的sec. 但是会超空间.. 标程的做法是用一个字符指针来记录每个结点表示的字符串, 即在一个结点中保存若干的字母而非仅一个字母, 当匹配一个新的单词, 到这个结点时只能匹配一半, 则把这个字符串再拆开成两部分( 匹配上的部分A和没匹配上的部分B ), B是A的孩子, 再把正在插入结点的未被匹配上部分作为A的孩子. 尽管可以构造出使这种方法mle的数据, 但实践证明没有出这种数据.. (我的代码是会mle的, 懒的写标程的代码了..)</p>
<p>附题目, 数据, 官方标程和我的程序. ( 数据比较大, 所以压缩了一下, 结果没太大效果.. )<br />
 猛击<a href="http://dqfind.com/blog/wp-content/uploads/contest/balkan07.tar.gz" target="_blank">这里</a>下载吧!</p>
]]></content:encoded>
			<wfw:commentRss>http://kmp.cc/blog/archives/464/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>准备noi2009时的oj笔记</title>
		<link>http://kmp.cc/blog/archives/615</link>
		<comments>http://kmp.cc/blog/archives/615#comments</comments>
		<pubDate>Fri, 05 Sep 2008 16:53:41 +0000</pubDate>
		<dc:creator>Find</dc:creator>
				<category><![CDATA[算法相关]]></category>
		<category><![CDATA[noi]]></category>
		<category><![CDATA[sgu]]></category>
		<category><![CDATA[题解]]></category>

		<guid isPermaLink="false">http://kmp.cc/blog/?p=615</guid>
		<description><![CDATA[这是我在准备noi2009时在online judge上的做的部分题目. 从wordpress的修订版本记录来看, 主要记的应该是2008年9月至2009年5月做的题目, 每题都附有简短的算法描述. 另外, usaco曾写过第三章之后几乎全部题解, 但因为Rob认为题解对使用usaco的练习者有害, 所以后来全部删除. 这里曾作为blog的一个页面存在, 现在在online judge上做题没有以前那样的耐心写感受, 即使某天忽然想写专门的题解了, 那也一定是值得我写一篇单独blogpost的收获, 所以这个页面只是留下来做纪念, 不再更新, 发布时间仍保留在2008年.
  btw, 我知道自己好没有恒心与毅力, 大家就不用留言鄙视我的题量了.
 

sgu
103 Traffic Lights
 边有规律时通时闭的图的最短路,仍用dijkstra.
 时间复杂度 O(n^2)
106 Traffic Lights
 数学方法. 有两大难点, 一个是多种零的情况的讨论, 另一个是精度问题.. 教训, 整数除法对负数的取整结果和使用的C编译器有关, 所以不要忽视强制类型转换!!
109 Magic of David Copperfield II
 一个魔术..找规律,构造
111 Very simple problem
 求高精度数X的开方的整数部分.手动开方
 时间复杂度 O(T^2),其中T为X的位数
114 Telecasting station
 求加权平均数
 时间复杂度 O(nlogn)
121 Bridges painting
 [...]]]></description>
			<content:encoded><![CDATA[<p><strong>这是我在准备noi2009时在online judge上的做的部分题目. 从wordpress的修订版本记录来看, 主要记的应该是2008年9月至2009年5月做的题目, 每题都附有简短的算法描述. </strong><strong>另外, </strong><a href="http://ace.delos.com/usacogate" target="_blank"><strong>usaco</strong></a><strong>曾写过第三章之后几乎全部题解, 但因为Rob认为题解对使用usaco的练习者有害, 所以后来全部删除. 这里曾作为blog的一个页面存在, 现在在online judge上做题没有以前那样的耐心写感受, 即使</strong><strong>某天忽然想写专门的题解了, 那也一定是值得我写一篇单独blogpost的收获, </strong><strong>所以这个页面只是留下来做纪念, 不再更新, </strong><strong>发布时间仍保留在2008年.</strong><br />
 <strong> btw, 我知道自己好没有恒心与毅力, 大家就不用留言鄙视我的题量了.<br />
 </strong></p>
<p><span id="more-615"></span></p>
<p><a name="sgu" href="http://acm.sgu.ru/teaminfo.php?id=011956" target="_blank">sgu</a></p>
<p>103 Traffic Lights<br />
 边有规律时通时闭的图的最短路,仍用dijkstra.<br />
 时间复杂度 O(n^2)</p>
<p>106 Traffic Lights<br />
 数学方法. 有两大难点, 一个是多种零的情况的讨论, 另一个是精度问题.. 教训, 整数除法对负数的取整结果和使用的C编译器有关, 所以不要忽视强制类型转换!!</p>
<p>109 Magic of David Copperfield II<br />
 一个魔术..找规律,构造</p>
<p>111 Very simple problem<br />
 求高精度数X的开方的整数部分.手动开方<br />
 时间复杂度 O(T^2),其中T为X的位数</p>
<p>114 Telecasting station<br />
 求加权平均数<br />
 时间复杂度 O(nlogn)</p>
<p>121 Bridges painting<br />
 <a href="http://www.briefdream.com/sgu-121/" target="_blank">WindyWinter</a>已经写的很详细了. 不同的连通块分开处理. 对于一个特定的连通块, 分根有一个孩子还是一个以上的孩子两种情况来讨论即可. 我两次都是想着想着就绕进去了.. 做题时脑子要清楚.<br />
 时间复杂度 O(n+m)</p>
<p>122 The book<br />
 好麻烦的一道构造题. 构造一个哈密顿回路, 由于每个点至少与剩下的点中的一半相邻接, 因此可以利用一个图论中的定理在多项式时间复杂度内构造出一个回路. 构造方法可以简述为 构造链 &#8211; 构造圈 &#8211; 拆成链.</p>
<blockquote><p>1. 尽可能在当前构造出的链的两端加点.<br />
 2. 不能加点时, 由每个点的邻接点个数可知, 链长至少为(N+3)/2. 链中有两端点的所有邻接点. 因此, 由抽屉原理可知, 必定存在点i, 满足i与链尾有边, i+1与链首有边. 于是拆开 i 和 i+1 之间的边, 连接 i 与链尾, 连接 i+1 与链首, 构造出一个环.<br />
 3. 如果此时所有点都已经在一个环内, 则程序结束. 否则, 找环中某个点k, 使其与某不在环中的点有边相连, 同时在这个位置打破环.<br />
 4. 回到第一步.</p>
</blockquote>
<p>写的时候还是有些晕, 所以花了很长时间写代码, 倒是没怎么调试.<br />
 时间复杂度 O( n^2 )</p>
<p>124 Broken line<br />
 计算几何,向右水平无限延伸,计交点个数<br />
 时间复杂度 O(n)</p>
<p>125 Shtirlits<br />
 搜索题, 数据范围很小, 随便加个剪枝就ac了. 开始以为3*3的格子中最坏只需要1~5五个数字就够了, 明明需要九个&#8230;</p>
<p>131 Hardwood floor<br />
 简单状态压缩</p>
<p>133 Border<br />
 排序<br />
 时间复杂度 O(nlogn)</p>
<p>136 Erasing Edges<br />
 大胆去做就可以过. 这道题的评测只是让你找到两组各n个数, 使这n个数之间两两的平均数等于给定值. 以x坐标为例.<br />
 a1+a2=2*x1, a2+a3=2*x2, &#8230; , a(n-1) + an = 2 * xn<br />
 确定一个数其他的数字跟着就出来了.<br />
 当n是奇数时, 2*xn-2*x(n-1)+2*x(n-2)-&#8230;+2*x1 = 2 * a1, 所以一定有解.<br />
 当n是偶数时, 2*xn-2*x(n-1)+2*x(n-2)-&#8230;-2*x1 = a1 &#8211; a1, 所以当方程左边为零时有无数多组解, 可以给a1任意值计算, 否则无解.<br />
 时间复杂度 O(n)</p>
<p>138 Games of Chess<br />
 我想到图论方面去了, 从amber牛的题解中知道还是构造.. 总的比赛场数显然是所有人的比赛次数之和的一半, 记为m. 因为一定有解, 所以任何一个人的比赛数不会超过m/2 ( 根据抽屉原理和一个人不能自己跟自己比赛 ). 我们可以把所有人按比赛场数的多少从大到小排序( 防止只有一场比赛的人中断比赛列表 ), 然后把他们依次填入比赛列表, 优先选择他们会赢, 当只剩一次比赛时选择他们会输, 再用剩余没有填入的人将比赛列表填满即可.<br />
 时间复杂度 O(n)</p>
<p>139 Help Needed!<br />
 见<a href="http://dqfind.com/blog/archives/491">http://dqfind.com/blog/archives/491</a>.</p>
<p>141 Jumping Joe<br />
 将题目中的式子变一下形就得到A*x1 + B*x2 = P. 因此, 只要找到满足方程的A, B, 且 | A | + | B | 与 K同奇偶且不大于K即可. 再通过一定的调整就可以得到题目的解了.<br />
 时间复杂度 O(nlogn)</p>
<p>142 Keyword<br />
 给定一个由&#8217;a'和&#8217;b'组成的字符串T, 求一个最短字符串s使s不是T的子串.<br />
 T的长度不超过50000, 因此我们可以知道s的长度不超过19 ( 长度为19的子串有2^19 &gt; 50000 ). 这样问题就简单了, 只要枚举s的长度, 找一个不在T里出现的字符串s即可.<br />
 时间复杂度 O(n)</p>
<p>143 Long Live the Queen<br />
 简单的树型dp. f[i]表示以i为根的子树中加上i所能得到的最大利润, f[i]=profit_of_i + sum ( f[ j ], j是i的孩子且f[j]&gt;0 ). 注意答案可能是负数.</p>
<p>146 The Runner<br />
 就是很简单的累加然后&#8221;取余&#8221;(被除数是浮点数),运算过程中可乘以10^4以消除小数点.但是发现<strong>读入</strong>带四位小数的浮点数就会出现误差. 所以只好按字符串读入数据,然后将整数部分和小数部分分别处理. 循环部分读入用c风格,iostream会导致超时. (居然要用&#8221;%I64d&#8221;而不是&#8221;%lld&#8221;, sgu的评测环境是windows?)</p>
<p>148 B-Station<br />
 可以说是模拟, 但需要一些技巧. 先统计出从i..j共有多少水, 然后设cut数组, 二分找到如果想使第i层自然跨掉, 至少需要从哪一层炸起, 并在这一层的cut值中加上第i层的建造费用.<br />
 我们只需要从第n层到第一层枚举, 每到一层就加上该层的p[i]并减去cut[i](即前面的部分楼层不需要再人工炸掉), 并记录最小值即可.<br />
 时间复杂度 O(nlogn)</p>
<p>151 Construct a triangle<br />
 用中线定理算出第三边的长. 将A固定在原点, B放在x轴, A和B的位置就很容易确定了. C是以A和B为圆心, 两个半径已知的圆的交点, 联立两圆求出两圆交点连线( 易知它与x轴垂直 ), 得到C的横坐标, 再用勾股定理算出它的纵坐标即可. 注意这个三角形的面积可以为零, 因此在无解的判断中要去掉等号.</p>
<p>152 Making round<br />
 我开始没明白题意. 题意是说让你把每个数占总数的百分比算出来, 百分比可以通过上入或下舍成为整数( 不一定是四舍五入 ), 要求百分比总和等于100. 所以..模拟就行了.</p>
<p>153 Playing with matches<br />
 动态规划的方程很容易想到, 但是n的值太大了. 我们发现每一个状态的胜负最多只和之前九个状态的值有关, 于是我们可以把这九位压成一个数, 不断递推, 直到出现重复, 这时便出现了一个循环, 可以很快求出n个火柴时的状态. 这样不同的状态数最多只有2^9-1=511种.<br />
 时间复杂度 O( B*m*k ), 其中B是不同状态的个数.</p>
<p>154 Factorial<br />
 数学问题.找n!中因子5的个数即是末尾0的个数.注意除5^k时k应大些(如14)<br />
 时间复杂度 O(logANS)</p>
<p>160 Magic Multiplying Machine<br />
 m的值很小, 于是我们可以维护一个f[i]表示i能不能拼出来, 每加进一个新数, 用现有的f[i]去和新数相乘得到更多可以拼出的数, 然后找一个最大的输出. 看成相加了, 交了n次都是wa on test 1, 囧..</p>
<p>163 Wise King<br />
 简单数学题<br />
 时间复杂度 O(n)</p>
<p>165 Basketball<br />
 逐步转化问题, 详见朱晨光2004年国家集训队作业.<br />
 时间复杂度 O(nlogn)</p>
<p>168 Matrix<br />
 发现取值范围是一个梯形,预处理一下就可以了<br />
 时间复杂度 O(nm)</p>
<p>169 Numbers<br />
 好玩的数学分析,发现满足条件的数都是11111…11*形的<br />
 时间复杂度 O(1)</p>
<p>171 Sarov zones<br />
 拿到题目就想到二分图匹配, 发现时空复杂都太高后发现只要贪心就可以了. 将所有人按重量由大到小排序, 再按这个顺序找到q<br />
 时间复杂度 O( mlogm + nm ), n是学生的总数, m是组的个数.</p>
<p>174 Walls<br />
 一个平面上,在线地建立一些墙, 当某一个墙与前面某些墙一起构成了一个封闭的平面, 输出这个墙的编号. 可以用哈希表加并查集解决, HASH函数随便设计, 主要用于查出某一个点在并查集中的序号, 然后对于每一个墙, 判断其两个端点在不在一个集合内, 若在, 说明构成了一个封闭平面, 若不在, 则把这个端点合并. SGU很不稳定, 这道题我交好多遍, 用同一个程序, 一会儿对, 一会儿错, 搞不懂.<br />
 时间复杂度 O(M), 有一个不算很大的系数</p>
<p>176 Flow construction<br />
 求有上下界的网络最小流, 建议先做194. 加一个t-&gt;s无穷大的边, 检查可行性, 记此时从s流出的流大小为g, 然后求 t-&gt;s 最大流 f 以求出正向最小流, 注意反向最大流不可超过g, 则答案为 g-f.</p>
<p>177 Square<br />
 一个正方形,不断的染色. 统计白色块面积.先建了n棵线段树,严重超时.后用二维线段树.<br />
 时间复杂度 O(mlongn)</p>
<p>178 Chain<br />
 每拆一个长度为L的chain, chain就变成1, x, L &#8211; x &#8211; 1这样三段, 如果拆k次, 则拆得k个长度为1的和k+1个长度不定的链. 为了不浪费链, 长度不定的链中最短的长为k+1, 次短的长2*(k+1), 然后是2*2*(k+1), 以此类推. 则拆k次最多可以拼出长为k+(k+1)*( 2^(k+1) &#8211; 1 )长度的chain. 所以我们只要枚举k直到所能拼出的最长chain大于n为止. 这个..对我来说有些难想到.<br />
 时间复杂度 O( logN )</p>
<p>183 Painting the balls<br />
 动态规划. 用 f[i][j] 表示最后一个选的是第i个, 倒数第二个是第i-j个, 则 f[ i ][ j ] = min ( f[ i - j ][ k ], k到i的距离不超过m ). 这样做时空均超. 改用f[i][j]表示最后一个选i, 并在i-j&#8230;i-1中选一个做倒数第二个, 则f[ i ][ j ] = min ( f[ i ][ j - 1 ], f[ i - j ][ m - j ] + p[ i ] ). 用滚动数组可以将空间复杂度优化到 O ( M^2 )<br />
 时间复杂度 O( n * m )</p>
<p>186 The chain<br />
 题意好难懂: 大概是说有n条链子, 每个链子上有若干个扣, 一个人每分钟可以解开一个链上的扣并用此扣链上任意两个链, 问最少要几分钟可以把所有链合并成一个链. 我用贪心, 每次解开最短的链上的一个扣并链上两个最长的链, 注意n=0的情况.</p>
<p>188 Factory guard<br />
 模拟题. 头晕, 在跨过0的地方相遇的条件总是表述不清楚, 其实就是只要两个人相向距离小于等于两人速度的绝对值的和就能相遇.<br />
 时间复杂度 O( N^2 * T )</p>
<p>190 Dominoes<br />
 将棋盘黑白染色, 根据颜色不同构成二分图再求最大匹配, 若能覆盖全部未删除的点, 则有解. ( 敲完就交, 一次ac, 最近几周来最有手感的一道题 ;) )<br />
 时间复杂度 O( N^4 )</p>
<p>193 Chinese Girls&#8217; Amusement<br />
 如果跳跃x次后再次回到1, 则xk mod N = 0, 且x是满足此式的最小的自然数. 因此可以想到要让每个人都被点到, 则必须让x=n, 即N和k互质. 问题转化成求不超过N / 2的最大数k, 使N和k互质. 分情况讨论:<br />
 当N是奇数时, 由(N-1)与N互质可知(N-1)/2与N互质, (N-1)/2即为答案;<br />
 否则, 当N/2是奇数时, ( N, N / 2 &#8211; 2 ) = ( N / 2 &#8211; 2, 4 ) = 1, ( N / 2 &#8211; 2 )即为答案;<br />
 否则, 即N/2是偶数时, ( N, N / 2 &#8211; 1 ) = ( N / 2 &#8211; 1, 2 ) = 1, ( N / 2 &#8211; 1 )即为答案.</p>
<p>194 Reactor Cooling<br />
 求有上下界的网络可行流. 对图不做任何修改, 直接套用判断有上下界网络流可行性的标程就可以了.</p>
<p>195 New Year Bonus Grant<br />
 给一棵树, 求最大匹配的个数. 树型DP很容易想到. 但居然贪心就可以了. 从叶子开始选发奖金的, 能选就选即可. 一个结点如果没被选, 那么它的孩子和父亲必定都已经被匹配了. 这时候如果拆掉父亲的自然是少一个多一个结果不变, 拆掉孩子的话, 那么孩子的孩子又没被匹配, 而匹配是从下往上进行的, 所以孩子的孩子肯定无法再进行匹配, 所以仍是少一个多一个结果不变.<br />
 时间复杂度 O(n)</p>
<p>196 Matrix Multiplication<br />
 给定一个矩阵A, 求A的转置矩阵B( 即b[ i, j ] = a[ j, i ] )与A的矩阵积的各元素之和. 根据矩阵乘法的运算法则, 发现答案其实就是B的每一列和的平方的和, 即A的每一行和的平方的和. 也就是将输入矩阵每一行i中&#8221;1&#8243;的个数统计出来记为c[ i ], 答案就是 c[ 1 ] * c[ 1 ] + c[ 2 ] * c[ 2 ] + &#8230; + c[ n ] * c[ n ].<br />
 时间复杂度 O( M + N )</p>
<p>197 Nice Patterns Strike Back<br />
 很容易看出是矩阵优化的状态压缩DP. 头一次用矩阵优化dp.<br />
 时间复杂度 O( m^3logn )</p>
<p>199 Beautiful People<br />
 先按第一个数据为第一关键字升序, 第二个数据为第二关键字降序排序, 把第一数据一样的看作一类, 则题目要我们求由不同类组成的按第二个数据得到的最长上升子序列. 套用经典的最长不下降子序列O(nlogn)算法就可以了.<br />
 时间复杂度 O( NlogN )</p>
<p>203 Hyperhuffman<br />
 求一篇文章用哈夫曼树编码后的长度. 数据排好了序, 因此可以再用一个队列, 每次取两个队列中较小的, 和加进answer, 并加到新队列的队尾. 原队列空了之后, 每次从新队列队首取两个, 再合并, 直到新队列中只剩一个元素即可.<br />
 时间复杂度 O( n )</p>
<p>207 Robbers<br />
 我想了个dp+贪心. f[ i ][ j ]表示到 i 个人用掉 j 个金块, 则f[ i ][ j ] = f[ i - 1 ][ j - k ] + 第 i 个人拿k个金块后的unfairness. 时间复杂度太高, 但想到这个k不用枚举太多, 大概在x[ i ] / y * m周围枚举三四个数就可以了. 再加个滚动数组降低空间复杂度就可以了. 看了一下Amber牛的, 先给每个人下取整的x[ i ] / y * m个金块, 然后按与期望获得的误差大小排序, 按误差由大到小多给一块金块就可以了. 我真脑残啊..<br />
 时间复杂度 O( nlogn )</p>
<p>210 Beloved Sons<br />
 按国王对儿子的喜爱顺序对王子们排序, 易知应该优先满足更受喜爱的王子. 匹配用类似KM算法的过程就可以了.</p>
<p>220 Little Bishops<br />
 n象问题. 动态规划. 把棋盘黑白相邻的染色, 相邻的两个格子染不同的颜色. 然后发现染白色的格子与染黑色的格子没有关系, 所以可以把两种格子分开处理. 以黑色为例. 把棋盘旋转45度, 则从第1行开始, 黑色方格的列数为1, 3, 5, 7, &#8230; , 7, 5, 3, 1. 可以把这些行等价的换成1, 1, 3, 3, 5, 5, 7, 7, &#8230; 然后每行只能放一个棋子, 每放一个棋子, 下面的行就少一个放棋子的选择. f[ i ][ j ]表示前i行放j个象. 方程为 f[ i ][ j ] = f[ i - 1 ][ j ] + f[ i - 1 ][ j - 1 ] * ( r[ i ] &#8211; j + 1 ), 即第i行不放棋子和放棋子两种选择, 其中r[ i ]为第 i 行的格子数目. 注意答案是int64型.<br />
 时间复杂度 O( nk )</p>
<p>221 Big Bishops<br />
 同220. 注意答案是高精度数字.</p>
<p>222 Little Rooks<br />
 记忆化搜索.<br />
 时间复杂度 O(n^2 * 2^n)</p>
<p>224 Little Queens<br />
 N皇后问题. 朴素搜索.</p>
<p>226 Colored graph<br />
 BFS. 注意两点之间可能有多条不同颜色的边.<br />
 时间复杂度 O(n^2)</p>
<p>230 Weighings<br />
 用比较信息构图, 拓扑排序即可. 注意可能有重边.</p>
<p>231 Prime Sum<br />
 注意到如果两个素数相加得素数, 则其中之一必为2 ( 否则相加为偶数 ), 问题就简单了.</p>
<p>236 Greedy Path<br />
 求最优比率环. 可以参考最优比率生成树的解法, 使用二分枚举答案 k, 然后构造 (k * time &#8211; cost) 为边的图, 用 bellman-ford 找负环, 如果存在负环则方案可行, 增大比率即可.</p>
<p>249 Matrix<br />
 先考虑一维情形.<br />
 n = 1时, 答案 000 001<br />
 n = 2时, 答案 000 001 011 010<br />
 n = 3时, 答案 000 001 011 010 110 111 101 100<br />
 可以发现, n每增加1, 新增加的就按把前面的逆序, 然后在新增加的位上置1.<br />
 类似的处理二维情形, ans[ i ][ j ] = f[ i ] &lt;&lt; m + f[ j ], 其中f[ i ]是一维情形是第i个数.<br />
 摘自amber牛题解.</p>
<p>259 Printed PR<br />
 贪心. 优先做需要较长时间来送货的.</p>
<p>269 Rooks<br />
 先将各行的列数按从小到大的顺序排序. f[ i ][ j ]表示前i行放j个棋子, 则f[ i ][ j ] = f[ i - 1 ][ j ] + f[ i - 1 ][ j - 1 ] * ( s[ i ] &#8211; j + 1 ), 其中s[ i ]是第i行的列数. 比较像220的解法. 答案要用高精度 ( 高乘低的高精度没注意低精度数字是0的情况, wa了n次 ).</p>
<p>271 Book Pile<br />
 给一堆书维护翻转和插入两种操作.用循环队列解决. 将顶上K本书放入队列中. ADD操作对应入队, ROTATE把front和rear换位即可.<br />
 时间复杂度 O(N+M)</p>
<p>274 Spam-filter<br />
 字符串处理. 有很多细节, 比如开头和结尾都不能有&#8217;.'( 即不能有空的word ), 这将导致wa on test 2; 不能有连续两个‘.’ ( 同样将产生空的word ); 不能用scanf读入字符串, 否则会忽略不该忽略的空白字符, 这将导致wa on test 3.. 考验耐心与认真.</p>
<p>275 To xor or not to xor<br />
 Amber牛的题解没看懂, 后来找到一个高斯消元的解决方法. 我们自然希望答案的64个二进制位上都是1, 但是情况不一定能得到满足, 于是我们要优先满足高位. 用f[ i ][ j ]表示 Ai 的第 j 位. 则第k个方程为<br />
 ( f[ 1 ][ k ] * x1 ) xor ( f[ 2 ][ k ] * x2 ) xor ( f[ 3 ][ k ] * x3 ) xor &#8230; xor ( f[ n ][ k ] * xk ) = 1<br />
 共计m个方程.<br />
 我们可以用xor操作消元. 从高位开始消. 最后把消元后仍能满足左右相等的方程所表示的位标记为1即可.</p>
<p>276 Andrew&#8217;s Troubles<br />
 模拟. 没说的.</p>
<p>282 Isomorphism<br />
 群论. 见<a href="http://dqfind.com/blog/archives/491">http://dqfind.com/blog/archives/491</a>.</p>
<p>296 Sasha vs. Kate<br />
 贪心. 从最高位开始确定要留下的数字(即可选数字中最大的), 并删去要留下之前的. 比如12934删去三个数字, 就先删12使9占最高位, 接着删去3使4占次高位.<br />
 时间复杂度 O(k^2)</p>
<p>297 Fair-play<br />
 求sum(si)%n.<br />
 时间复杂度 O(m)</p>
<p>299 Triangle<br />
 排序, 再逐一枚举相邻三个边即可.</p>
<p>326 Perspective<br />
 显然球队1最多赢得 r[1]+w[1] 场比赛, 记为X. 将比赛作为点集A, 球队作为点集B, 添加源点s, 汇点t. 与球队1有关的比赛不列在图中 (显然这些比赛的赢家是球队1). 如果i, j之间有 rem[i][j] 场比赛, 则从 s 向表示 i, j 之间比赛的结点 k 连一条边, 容量为 rem[i][j], 从 k 向表示球队 i 和球队 j 的结点各连一条边, 容量为无穷大. 从代表每个球队 i 的结点到汇点 t 连一条边, 容量为 X-w[i](如果该容量为负则可以直接判定无解). 做从 s 到 t 的最大流, 如果最大流等于从源点 s 出发的边的容量之和则有解, 否则无解.</p>
<p><a name="spoj" href="http://www.spoj.pl/users/alft" target="_blank">SPOJ</a></p>
<p>1 TEST<br />
 模拟.</p>
<p>2 PRIME1<br />
 生成40000以内素数表, 再对每个输入范围内的数字一一判断.<br />
 时间复杂度 O(t*(n-m)*k), 其中k是一个不到40000的小常数. 实际很快, 我的程序2.x秒就出解了.</p>
<p>5 PALIN<br />
 一道构造的题目. 将数字的前半部分对称的贴到后面, 如果不符合条件则给最中间的数加1再做一次.<br />
 时间复杂度 O( K * len ), 其中len是数字串的长度.</p>
<p>51 TOUR<br />
 分析后发现如果a能赢b就连一条a-&gt;b边, 得到一个图, 图中所有能到其他所有点的点即为满足的点. 暴力做会超时, 对图求一次强连通分量, 如果存在唯一一个入度为0的连通块则答案为连通块内点的个数, 否则答案为0.<br />
 时间复杂度 O( n + m )</p>
<p>53 KAMIL<br />
 乘法原理解决.要求代码尽可能短, 我用c++写了一个229字节的代码, 去掉了所有空白字符. 据yangyi巨牛的表格, 此题用PERL, RUBY等语言解决得分更高.<br />
 时间复杂度 O( L ), L是输入字符串长度.</p>
<p>54 JULKA<br />
 简单的解方程, 加上高精度运算. 第一次写操作符重载, 爽..</p>
<p>58 PICAD<br />
 排序, 然后统计.</p>
<p>66 CRSCNTRY<br />
 求两串的最长公共部分, 就是位置不一定要连续. 简单的二维dp, 没有任何陷井.</p>
<p><br class="spacer_" /></p>
]]></content:encoded>
			<wfw:commentRss>http://kmp.cc/blog/archives/615/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
