blockade写疵了……
在贪心的部分的一个x++忘写了囧……
再加上Day1完跪,估计本沙茶这次AH Top10都进不去了囧……明年省集训队有危险了囧……(据最新消息,由于AH太弱了,Top10还是稳的囧……)

看来这么长的综合题代码不对拍确实很危险……
但又有谁让我写得这么慢木有时间对拍了呢……

为什么挂得这么惨呢?
基本的模板写得太不熟了,一遇到综合题就慢,drive和blockade挂掉都是这个原因囧……
还有,一遇到长代码的题就畏惧……本沙茶在写blockade代码的时候,连写add_edge时手都在抖,心发慌……以至于这个200-行的代码写了2h+……

之前的N多模拟赛,本沙茶都考得很好,但是有个毛用……毕竟当时这种类型的题木有出……

剩下就木有可说的了囧……虽然这次挂了,但是只要吸取教训,下次一定能翻身!!!!!!!!!!!
AHOI2013 我要复仇!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

Orz AK的大神!!
@hqztrue
@roosephu

posted @ 2012-11-19 17:58 Mato_No1 阅读(838) | 评论 (0)编辑 收藏

【Day1】
vigenere:不说了;

game:
方法一(本沙茶在现场的做法,60分):
设i的左右手为A[i]和B[i]。二分最大的金币数D,则第i个人要满足其前面所有人(包括国王)的A之积不超过S[i] = (D+1) * B[i] - 1。
考虑站在最后的那个人,显然除了他以外的所有人(包括国王)的A之积不能超过他的S值,如果木有人满足此条件则无解,否则取满足此条件的A值最大的人,放最后(因为若某个合法方案最后不是满足此条件的A值最大的人,则把那个A值最大的人与他交换,仍然是合法方案),然后删掉这个人,转化为子问题,直到所有人都删掉为止,此时必然有解。
此方法时间复杂度为O(N2 * log2MAXW),其中MAXW为D的上限,由于60%的数据D<=109,所以MAXW取109
显然这个方法是不能再加高精度了,否则必T,问题是计算所有人的A之积时会超过long long范围,解决方法:由于A和B的上限是104,D的上限是109,所以有解时必然有所有人的A之积<=109 * 104 * 104 = 1017,因此在过程中若超过这个值,必定无解,直接卡掉。

方法二(正解):
把所有的人按照A*B递增排序,就一定是最优解,剩下的就不解释了(需要高精度乘除单精度)。
证明:
若某方案不是将所有人按照A*B递增排序的,则必然存在i使得A[i]*B[i]>A[i+1]*B[i+1](这里的i是排序后的编号,不是原来的编号),下证交换i和(i+1)之后解必然不会变差。
设i前面所有人(包括国王)的A值之积为S1。
交换前,i的金币数为S1/B[i],(i+1)的金币数为S1*A[i]/B[i+1];
交换后,i的金币数为S1*A[i+1]/B[i],(i+1)的金币数为S1/B[i+1];
注意这里S1*A[i]/B[i+1]显然不小于S1/B[i+1],而S1*A[i]/B[i+1]-S1*A[i+1]/B[i]=S1*(A[i]*B[i]-A[i+1]*B[i+1])/(B[i]*B[i+1])>0,因此交换前(i+1)的金币数不小于交换后i和(i+1)的金币数,而除了i和(i+1)外,其他人在交换前后金币数都不变,因此总的金币数的最大值不会变大,即解不会变差。证毕。

这两种解法都是贪心,但它们是从不同的角度入手的——方法一是“分阶段贪心”,证明需要分别证最优子结构性质和贪心选择性质;方法二是“排序贪心”——在一类有关最优顺序的问题中,一般解法不是贪心,就是二分图或网络流模型(当然小数据也可以状压),如果用贪心,只要找到一种排序方法(对某个值排序),使得若不这样排序则把相邻逆序的元素交换后能够得到不更差的解,做法就是正确的。

drive:(本沙茶想出正解了,可是实在写不完,后来交暴力了囧——真真真真真真真真真真真真真真真真真真真真真真真真真真真真真真悲剧)
首先求出S1[i]和S2[i]分别表示i往右最近的和第二近的位置,这个用平衡树可以解决;
然后,每个位置i拆成两个点i.A和i.B,分别表示从这里出发,A先开和B先开。i.A往S2[i].B(如果有的话)连一条边,边权为两位置距离,i.B往S1[i].A(如果有的话)连一条边,边权为两位置距离。由于不会有环(S1[i]、S2[i]均>i),所以是森林。
然后,设F1[i]和F2[i]分别为从i走到根结点,A开的长度和B开的长度,这个BFS一下就可以了囧。
对于第一问,设W[i]为从i往上走,总长不超过X0时最远能走到哪里,显然只要从下到上求W,类似单调队列乱搞即可;求出W后,枚举每个点i,用记录的F1和F2值可以求出i到W[i]路径上A开的和B开的长度,找比值最小的即可;
对于第二问,可以在求出森林后用树的路径剖分搞,但更好的做法是倍增:设SUM[i][k]表示从i往上走2k条边的总长度,SUM可以在预处理中求出,做第二问时,只需要在SUM里调就行了,一次操作的时间复杂度O(log22N)。
显然这是个数据结构综合题,巨繁琐(估计代码要超过10K),本沙茶当时花了1h+写,后来发现肿么也不可能写完了,就交暴力了囧(早知道一上来就写暴力了,这样或许能想出来game的正解啊啊啊啊啊啊啊啊啊……哭死……)

总之Day1跪得不成人形了……

【Day2】
mod: 不说了;

classroom:线段树是可以AC的,只不过要把两个操作(找最小值和区间减法)放一起;
当然,本题的正解是,二分M0,然后看前M0个操作是否能全部满足:将每个操作(l, r, D)拆成(1, r, D)和(1, l-1, -D)(当l>1时),这样所有操作的左端点都是1了,设S[i]为右端点为i的所有操作的D之和,这个显然可以在线性时间内得到,则点i的变化量就是S[i..N]之和,这个在求出S[i]后从后到前扫描一下即可得出,也是线性,如果所有的变化量加上原来的值都不小于0,则前M0个操作都能满足,否则就不是都能满足。
这样,时间复杂度仍是O(NlogM)的。更好的方法是,借鉴倍增的思想,如果前M0个可以满足,就把前M0个都满足(把所有点都加上变化量),接下来就不用考虑前M0个操作了,只在后面继续二分。这样,算法的时间复杂度就是线性的了。

blockade:
【首先每个军队往上走当然是最好的,但不能在根上停住。
因此,二分最长时间D(注意D<=5*10^13),然后先看不能走到根的军队,一直往上走直到时间到了。
然后看能走到根的,先让他们全到根上,然后,对于那些“还有叶结点木有被控制的”根的子树(防止断句错误),用那些走到根上的来控制,用贪心解决……
本沙茶就这么写的,写了180+行,也查完了,可是在结束前5min时突然发现漏了一种情况——
某些能到根的军队可以不走到根,直接停在根的子结点处,控制这棵子树。
可是已经来不及了,最后就木有考虑这种情况……而且这种情况还比较普遍……】
这种情况的解决办法:
如果某个军队能走到根,但让它再走一步,走回到它所在的那个根的子结点,就来不及了的话,就让它停在根的子结点处,控制它自己的子树。这是因为,如果它去帮别的子树,必然就有第三个军队要来帮它。设它所在的那个根的子结点为B,它去帮的子结点为A,帮它的第三个军队所在的根的子结点为C,由于它自己走不回来,所以第一次走到根的子结点处的剩余时间T<2*W(root, B),而它能去帮别的子结点,所以T>=W(root, A)+W(root, B_,可得出W(root, A)<W(root, B)。第三个军队能来帮它,所以第三个军队剩余的时间>=W(root, B)+W(root, C_,自然>W(root, A)+W(root, C),所以这第三个军队也能去帮A,因此,让原来的军队停在B,第三个军队去帮A,也是合法方案。
注:本题灰常麻烦,需要用到树DFS、BFS、倍增(这个和drive肿么一样啊囧……),本沙茶写的时候还用上了线段树囧……

总之Day2也跪了,但不像Day1那么惨囧……
总之Day2比Day1跪得更惨囧……

posted @ 2012-11-14 21:04 Mato_No1 阅读(885) | 评论 (2)编辑 收藏

水题就不说了囧……

【1】Oct.30 TYVJ “扫地”杯III NOIP2012模拟赛 day1
(本沙茶这个其实木有参加,是之后捉的……还好AK了囧……Orz liouzhou_101!!)
第一题:
若n=1,则只有当y=x*x时才有唯一解x(这个一定要特判);
若n>1,由柯西不等式得(a22+a32+...+an2)(1+1+...1(n-1个1)) >= (a2*1+a3*1+...+an*1)2
即(n-1)(y-a12)>=(x-a1)2,当且仅当a2~an全部相等时等号成立。
显然a1的最大、小值一定是零点,也就是求方程(n-1)(y-a12)=(x-a1)2的解的问题,若Δ<0则无解,否则求两解之积,可用Vieta定理得出。

第三题:
先求出最短路图(求出S到每个点的最短距离dist0[]和每个点到T的最短距离dist1[],然后边<i, j>属于最短路图当且仅当dist0[i]+<i, j>长度+dist1[j]等于S-T最短路长),然后那些能炸掉的点就是最短路图的S-T割点(当然S、T本身不能算,另外,最短路图其实应该是个有向图,但这里当做无向图处理),只要对S、T所在的连通块做Tarjan即可。
注意这里最短路的求法:SPFA或许也能过,但由于其不稳定,在比赛的时候如果时间够的话还是写Dijk+heap吧囧……

【2】Nov.2 TYVJ 「Clover 10」杯HE两校联赛(第二轮Day1)
(这个也木有参加,是之后捉的……另外说一下,第二题的题目描述与数据不符)
第三题:
正解见This_poet神犇的空间。
这里说一下本沙茶的方法(70分):
设F[i][s]表示对X[1..i]进行设置,范围是[1..s],且从1能够“走出去”(走到大于i的结点)的方案总数,这里有s>i。
枚举“指出去”(X值大于i)的最小的结点为j(1<=j<=i),则有
F[i][s]=∑(F[j-1][i] * (s-i) * si-j),1<=j<=i。
边界:F[0][i]=1(本身木有意义,在乘的时候作为单位元)
这很容易理解。j是要指出去的,因此i+1<=X[j]<=s,有(s-i)种;对于X[1..j-1],由于j是指出去的最小结点,所以它们都不能指出去,X值范围1..i,但是它们必须“指出j-1",就是走到j及其后面的部分,否则就会被困住,自然也就走不出去了,所以是F[j-1][i];对于j+1..i,它们可以随便指,1<=X值<=S,因此是si-j
但是,这个递推式再也无法优化下去了,题目要求O(N2)显然无法办到。
而在正解中,我们关心的不是从1能不能走出i,而是从1最远能走到哪里。这时列出来的递推式就很容易优化到O(N2)。所以,在递推和DP问题中,思路的不同,将会引发完全不同的结果,当一个递推式/转移方程无法优化下去的时候,可以换一个思路来求解。

【3】Nov.3 TYVJ 「Nescafé 29」杯HE两校联赛(第二轮Day2)
第一题:
二分r,求出每个半圆能覆盖到的线段,再看这些线段的并是否为[0, x0]即可。问题就是求线段并的操作是比较易疵的。
首先将所有线段按照左端点递增排序,然后扫描每条线段,并记录目前线段达到的最右位置(就是右端点最大值)maxr,若某条线段的左端点大于前面的maxr则不能覆盖,扫描完了以后,再看第一条线段的左端点和所有线段的maxr是否符合要求即可。
但是,对于本题要注意:(1)由于有可能相离,因此最后的线段数可能不足N条,尤其要注意一条线段都木有的情况;(2)(极其易疵)题目只要求覆盖线段[0, x0]即可,因此,即使在x0右边发现了中断处(左端点大于前面maxr),也木有关系!!(本沙茶当时就在这里搞疵了,跪了2个点);

第二题:
本沙茶当时使用搜索骗的……可是它的数据实在太弱,本该AC的(最后还是跪了一个点,原因是卡时:ZZZ = ?? / m0,忘了考虑m0=0的情况);
首先求出图的每个连通块,如果某连通块内的所有结点初始权值之和不为零,无解。否则求出这个图的最小生成森林(用Kruskal),作为初始解(其实很多情况下这就是最优解囧)。
然后开始DFS,使用改变搜索顺序优化:先考查两端点权值都不为零且为相反数的边(因为转移之后可产生两个0点),再考查两端点权值都不为零且不为相反数的边(转移之后可产生一个0点,注意双向转移),最后考查两端点权值有一个为零的边(将0点转移,不会产生新的零点),其它的决策显然不明智。此外每条边只能转移一次。
当然直接这样搜肯定是要T的,但最优解会很快求出,因此可以卡掉。这题可以加启发函数,但本沙茶不加也木有事囧……

第三题:
递推式不说了。注意满足条件的树的高度的范围其实很小(<=16),所以在找到高度上下界之后是不会T的。注意对于结果小于10^8的处理(不需输出多余的0),此时N<=34;

【4】Nov.5 VIJOS NOIP2012模拟赛第三弹
第一题:
容易证明,最优解中虫洞的左端点一定是最左的点。
二分最大距离dist,然后离最左的点距离<=dist的显然都能走到,>dist的则只能使用虫洞。设离最左的点距离>dist的左起第一个点为S,则从S往右枚举每个点为虫洞右端点时,离S的距离和离最右点的距离是否都不大于dist,若都小于,则右端点可以在这里,dist符合条件。

【5】Nov.7 TYVJ NOIP2012提高组模拟赛day1
全是水题,不说了。注意第二题是保留整数而不是四舍五入,第三题的“差”不是“差的绝对值”!!!!!!!!!!!!!!!

【6】Nov.8 TYVJ 「Poetize 10」杯NOIP2012提高组模拟赛day2
第一题:
首先要模型转化一下,题目就是:在一棵树上,每个结点都有一个权值,除根结点外,每个结点都有一个容量(这个容量在题目中是体现在父边上的),选定若干结点,使得树中除根结点外的每个结点子树中选定结点的权值之和都不大于其容量,问最多能选多少结点。
由于数据范围小,本沙茶用类似树形背包的DP硬搞掉了,其实是可以贪心的囧……将结点按权值递增排序,每次选择一个所有祖先容量全部足够的权值最小的结点,最后得到的一定是最优解。
证明:由于决策之间不互相影响,最优子结构性质显然满足,下证贪心选择性质。设目前所有祖先容量全部足够的权值最小的结点为A,某方案中权值比A小的结点的选定情况(就是之前的状态)与选A的方案相同,但木有选A。设该方案中选定的权值不小于A且与A的LCA深度最大的结点为B,LCA(A, B)=P,由于B的权值不小于A,所以若将B删掉,A选上,其到根的路径上P及其以上的部分显然不会超过容量限制,对于P以下的部分,由于P是最深的LCA,因此P以下的部分根本木有被权值不小与A的结点所占用,因此肯定也不会有事,所以,将B删掉、A选上,将得到一个不比原方案差的可行方案,所以贪心选择性质满足。综上,贪心算法是正确的。

第二题:
先将区间按照右端点递增排序,然后扫描:设目前区间的右端点为r,上一个区间的右端点为r0(这里忽略右端点相同的情况,即必有r>r0),则在[r0+1, r]这一段里的最优解有两种可能:(1)若目前区间及其之后的区间内有左端点小于r的,则最优解为r;(2)若目前区间及其之后的区间的左端点全部不小于r,则[r0+1, r]这一段里各个值的能量总和均相同,为保证最小,最优解为r0+1。
接下来的问题是如何快速求出E=r或r0+1时的能量总和。显然在之前的区间里都不能获得能量,后面的区间内,左端点小于等于E的区间的能量为左端点的值,否则为E。由于前面的区间的右端点都小于E,左端点自然小于等于E,所以“后面的区间内,左端点小于等于E的区间个数”就是全部区间内左端点小于等于E的区间个数,这个可以在预处理中将所有左端点递增排序之后用二分查找得出,这些区间的左端点和值也可以记录一个S值来得出,而左端点不小于E的区间个数就是(该区间及其后面的区间总数-左端点小于等于E的区间个数)。
总时间复杂度O(NlogN);

第三题:
这个题真是折腾死人了囧……其实做法很简单,但巨难想到……
首先把待匹配字符串(设为A,匹配串设为B)展开成2倍的形式,所有的循环串就是所有长度为N的子串了囧……
设F[i][j]为A(展开后的)第i个字符往前,至少到哪才能与B[0..j]匹配(也就是所有能与B[0..j]匹配的A[k..i]中的k的最大值)。显然这样一说,转移方程就出来了囧:
若B[j]="*",则F[i][j]=max{F[k][j-1], k<=i}
若B[j]≠“*”,则F[i][j]=F[i-1][j-1](当A[i]=B[j]时)或-INF(当A[i]≠B[j]时),注意边界:j=0时,B[j]必为"*"(根据下面的假设),此时F[i][j]=i+1(不是i!!为了后面的决策),而i=0时,若B[0..j]均为“*”则为1(不是0,同理)否则为-INF。
对于max{F[k][j-1], k<=i}这里,显然可以用辅助数组搞定,注意辅助数组是要滚动的,否则会MLE(其实F也可以滚动);
接下来,若B[0]="*",则求出F之后只需要看对于每个i(i>=N-1,N为原长),F[i][M-1](M为B的长度)是否>=i-N+1即可,因为前面的部分都可以用这个*干掉。
若B[0]≠"*",则将B最前面的不为"*"的部分拿出来,显然这里是要硬性匹配的,因此先求出这里能匹配A的哪些位置(KMP用不用都可以),B剩下的部分按照B[0]="*"处理,只是最后在找的时候只能找原来B前面硬性匹配的部分可以配上的位置。
若B里面木有"*",就是普通的字符串匹配的问题了,直接特判掉(同样不必KMP)。这个比较容易漏掉。
总时间复杂度O(NM)。
———————————————————————————————————————————————————
大概也就这么多了囧……以后就再也木有NOIP级别的模拟赛了……真希望明年7月做NOI模拟赛也能像现在这样啊囧……
———————————————————————————————————————————————————
后记:模拟赛成绩这么好,最终还是挂了……谁叫自己怕繁琐题呢囧……

posted @ 2012-11-09 21:36 Mato_No1 阅读(640) | 评论 (0)编辑 收藏

原题地址
这是个超级大水题,我太沙茶了,想傻了N久……后来才反应过来……所以要写一下作为警示。

首先这个序列就是一个堆……
因此,问题也就是说N个结点,权值刚好取遍1~N的堆的总数……
设结果为F[N]。设N个结点的堆,左子树有l个结点,右子树有r个结点(显然有l+r+1=N),则有
F[N]=C(N-1, l) * F[l] * F[r]
这个理解起来很容易囧……因为根结点只能是1,左子树和右子树显然也都是堆,因此相当于在2~N中取l个数组成左子树,剩下的数组成右子树……又因为不管取哪些数,左右子树的组成方法总数都是F[l]、F[r](只与次序有关)……这样就得到上面的式子了囧……
C(N-1, l)=N! / l! / r!,因此需要预处理出来A[i] = i! mod P,然后除法用逆元就行了囧……

不过,本沙茶一开始想按照层数枚举,然后相乘……自然搞不出来囧……后来又用暴力把N<=15的结果拿出来分析,想找到规律……结果毫无规律……后来又纠结了N久才想到上面这个……真正比赛的时候就悲剧了囧……所以要警示一下……

代码:
#include <iostream>
#include 
<stdio.h>
#include 
<stdlib.h>
#include 
<string.h>
using namespace std;
#define re(i, n) for (int i=0; i<n; i++)
#define re1(i, n) for (int i=1; i<=n; i++)
#define re2(i, l, r) for (int i=l; i<r; i++)
#define re3(i, l, r) for (int i=l; i<=r; i++)
#define rre(i, n) for (int i=n-1; i>=0; i--)
#define rre1(i, n) for (int i=n; i>0; i--)
#define rre2(i, r, l) for (int i=r-1; i>=l; i--)
#define rre3(i, r, l) for (int i=r; i>=l; i--)
#define ll long long
const int MAXN = 1000010, INF = ~0U >> 2;
int n;
ll MOD, A[MAXN], F[MAXN], res;
void init()
{
    cin 
>> n >> MOD;
}
void prepare()
{
    A[
0= A[1= 1; re3(i, 2, n) A[i] = (A[i - 1* i) % MOD;
}
void exgcd(ll a, ll b, ll &x, ll &y)
{
    
if (b) {
        ll _x, _y; exgcd(b, a 
% b, _x, _y);
        x 
= _y; y = _x - (a / b) * _y;
    } 
else {x = 1; y = 0;}
}
void solve()
{
    F[
0= F[1= 1int s = 1, l = 0, r = 0; ll x, y;
    re3(i, 
2, n) {
        
if (l == s) {
            
if (r == s) {s += s + 1; l++;} else r++;
        } 
else l++;
        F[i] 
= F[l] * F[r] % MOD; F[i] = F[i] * A[i - 1% MOD;
        exgcd(A[l], MOD, x, y); F[i] 
= F[i] * x % MOD; if (F[i] < 0) F[i] += MOD;
        exgcd(A[r], MOD, x, y); F[i] 
= F[i] * x % MOD; if (F[i] < 0) F[i] += MOD;
    }
    res 
= F[n];
}
void pri()
{
    cout 
<< res << endl;
}
int main()
{
    init();
    prepare();
    solve();
    pri();
    
return 0;
}

posted @ 2012-10-30 21:35 Mato_No1 阅读(1040) | 评论 (1)编辑 收藏

和以前的总结一样,那些是人都会搞的水题就不写了囧……

【1】 Sept.29 「Poetize」杯NOIP模拟赛 VI
第一题(TYVJ P1962):
枚举及其优化。
设F[i][S]为买的方案为S(用10位二进制表示)时,能不能表示出整数i(1<=i<=100),这个显然可以预处理出来,然后将所有的状态S按照“第一关键字为买的个数递增,第二关键字为题目中的T递增“排序。枚举时,只需要按照排序后的顺序从前到后枚举状态,找到第一个能表示出所有给出的整数的状态即可。最坏情况下是10000*1024*10,会T,但题目中木有这样的数据囧……

第二题(TYVJ P1963):
DP,思想非常另类的那种……
每秒只有三种可能状态:不进行(0)、准备进行(1)、进行(2),且0的下一个状态是0或1,1的下一个是2,2的下一个是2或0,所以,假设时间是顺序的,设F[i][j][x]表示前i秒中状态1或2的有j秒,第i秒的状态是x的最大值……(剩下的不说了,注意第一个状态必须是0或1)
下面考虑时间是环形的情况。可以发现,只要每两个相邻状态都满足“0的下一个是0或1,1的下一个是2,2的下一个是2或0”,就是合法的,不过,最后一个状态也有下一个状态:第一个(因为时间环形)。
如果N=B,则所有的状态都可以为1或2,只需要找到U值最小的那一秒,将它的状态设为1,其它状态设为2即可;(特判掉)
如果N>B,则必然有状态为0,也就是可以从它开始。所以,时间仍然可以按照顺序的看待,只是注意若第一个状态是2,则最后一个状态不能是0——将第一个状态为0、1的与为2的分开处理即可。
注意,N=0与N=1时需要特判。

第三题(TYVJ P1964):
为了描述方便,可以将这个序列在格子中表示,如下图,表示序列(3, 4, 5, 4, 6, 3):
设最终的序列中每个数都为S。以下起第S行为界,上方的黑格需要消去,下方的白格需要补上。由于题目中只允许每次对连续的一段加1或减1,也就是消去同一行连续的一段黑格或补上同一行连续的一段白格,所以,容易证明,此时的最少操作次数就是(下起第S行上方各行的连续黑格段数之和+下起第S行下方各行的连续白格段数之和)。因此,问题就是枚举S并维护这个和值。
首先,预处理算出S=0的和值。此时只有黑格段没有白格段。虽然行数很多,但本质不同的行最多只有N个,所以可以在O(N)时间内求出(当然先要进行一个O(NlogN)的排序)。具体求法就不说了囧……
然后,考虑当S从0开始增加时,和值如何变化。显然,S从x增加到x+1,和值的增量是(第x行的白格段数-第(x+1)行的黑格段数)。由于每一行都是白段与黑段交替的,所以,若第x行与第(x+1)行本质相同,则和值增量只可能是1(第x行最左边和最右边的格子都是白的)或0(第x行最左边和最右边的格子一白一黑)或-1(第x行最左边和最右边的格子都是黑的)。第一个和最后一个格子的颜色只与最初序列中第一个和最后一个数有关,且必然下起一开始若干行都是-1,然后是0,再然后是1……也就是和值一开始不断减少,然后不变,然后不断增加,那么,不变阶段的和值就是最小值,其长度就是最小值的个数;
问题是如果第x行到第(x+1)行发生改变肿么办。此时,必然在原序列中有元素值为x,只需要把它们所在的位置的颜色从黑的改为白的即可。注意,在维护段数的时候,需要考虑到该格的相邻的格子的颜色,还需要注意边界。这样的操作有N次,所以,时间复杂度是O(N)的。
综上,可以求出在每一个本质不变的行段内的最小值及其个数,取最小的即可。总时间复杂度为O(NlogN)(最初的排序)。

【2】Oct.4 「Poetize」杯NOIP模拟赛 VII
第三题(TYVJ P1993):
注意到任意一个数能一步变换到达的数最多9*10+C(10, 2)=135个,只需要枚举一下,然后用二分查找找出这个数在不在(不能用Hash,会扎堆),若在就连一条边,然后求这个图的s-t最短路即可,需要使用Dijk_heap(SPFA估计会被卡,注意手写堆,不要priority_queue)。这样对于题目中的数据可以卡线通过(最坏情况下仍然会T,估计正解是某种设计比较好的Hash)。注意,使用DL边表时,需要在空间上作一些优化,否则可能MLE。

【3】Oct.20 Tyvj三周年邀请赛
第一题(TYVJ P2011):
压位即可。

第三题(TYVJ P2013):
首先转移方程是很好搞的……F[i]为前i个数的最大权值,则F[i]=max{F[i-1], F[j]+A[j+1]*B[i], 0<=j<=i-2},边界:F[0]=F[1]=0。问题是如何优化。
首先,由于A、B序列木有单调性,一般的斜率优化是不行的囧……
注意F[j]+A[j+1]*B[i],当F[j]求出来之后,这个其实是一个自变量为B[i]的一次函数,也就是一条直线(斜率A[j+1],纵截距F[j]),而且,由于B非负,所以这其实只是这条直线在y轴右侧的部分(射线!!)
本题需要维护的就是这些射线组成的下凸壳。注意,F数组是递增的,也就是插入的射线的纵截距递增。这样,插入射线y=A[j+1]*x+F[j](x>=0)时,(0, F[j])这个点要么在原来的凸壳上(如果大于上一个F[j]),要么在原来的凸壳内部。
如果在内部,则这条射线与原来的凸壳最多只有一个交点,因此只需要从左到右扫描原来的凸壳的边(这些边除了最右一条是射线外,其余都是线段),将一开始的在待插入射线下方的边都删去,直到找到一条边与该射线相交或者所有部分都删去为止。若某条边与待插入射线相交,则删去它在待插入射线下方的部分,再插入新射线,否则直接插入新射线;
如果在凸壳上,那么新射线有两种可能:一是斜率不大于上一条射线的斜率,此时该射线完全在凸壳外或凸壳上,直接舍弃;二是斜率大于上一条直线的斜率,此时,把原来凸壳上最左的那条边删掉,再按照内部的情况处理即可;
求F[i]时,找到x=B[i]与凸壳的交点即可;
显然,这些边可以用一个栈来维护(本沙茶一开始以为是队列,写完了以后才发现是栈……于是代码中按照队列的格式来写的囧……),每条射线最多进栈一次,出栈一次,加上二分查找的时间,总时间复杂度O(NlogN)。
写的时候注意一些细节,尤其要注意的是,算出F[i]后不能马上插入射线i,而要在F[i+1]算出后才能插入,因为j<=i-2!!(同样的,一开始也只能插入0,不能插入1)

代码:
P1962 P1963 P1964 P1993 P2013

posted @ 2012-10-24 15:27 Mato_No1 阅读(395) | 评论 (0)编辑 收藏

原题地址
本沙茶在2009年1月曾经在RQNOJ上捉过这题,那时候是很难的题,现在就很水了囧……(当然,本沙茶那个时候不会exKMP,是用暴力的,可是时间复杂度仍能是O(N3))。

F[i][j]=min{F[i][k]+F[k+1][j],min{((j-i+1)/(k-i+1)的十进制位数)+2+F[i][k],k-i+1}, i<=k<j,第二项需要满足原字符串[i..j]这一段恰好由[i..k]这一段的若干次复制得到}
(加上k-i+1是因为对于以下三种重叠字符串,不压缩比压缩要短:AA型、AAA型、ABAB型)
边界:F[i][i]=1;

问题是在上述方程的第二项里如何求出可行的k。显然,只需要对[i..j]这一段作exKMP,求出nx,然后k可行当且仅当满足:(1)nx[k+1]=j-k;(2)(k-i+1)|(j-i+1);

不过,本题在写exKMP的过程中会出现很囧的问题……由于下标不是从0开始,而是从i开始,所以很多地方关于下标的计算都要改掉,非常不方便,而且很容易疵掉。与其这样,还不如把[i..j]这一段复制到一个新字符串里,下标从0开始。对于其它的某些字符串算法和数据结构,或许也是这样囧……

代码:
#include <iostream>
#include 
<stdio.h>
#include 
<stdlib.h>
#include 
<string.h>
using namespace std;
#define re(i, n) for (int i=0; i<n; i++)
#define re1(i, n) for (int i=1; i<=n; i++)
#define re2(i, l, r) for (int i=l; i<r; i++)
#define re3(i, l, r) for (int i=l; i<=r; i++)
#define rre(i, n) for (int i=n-1; i>=0; i--)
#define rre1(i, n) for (int i=n; i>0; i--)
#define rre2(i, r, l) for (int i=r-1; i>=l; i--)
#define rre3(i, r, l) for (int i=r; i>=l; i--)
#define ll long long
const int MAXN = 110, INF = ~0U >> 2;
int n, F[MAXN][MAXN], nx[MAXN], res;
char ss[MAXN + 1], ss0[MAXN + 1];
void init()
{
    scanf(
"%s", ss); n = strlen(ss);
}
int sol0(int l, int r)
{
    
int W = r - l + 1; re3(i, l, r) ss0[i - l] = ss[i];
    nx[
0= W; nx[1= nx[0- 1; re(i, W) if (ss0[i] != ss0[i + 1]) {nx[1= i; break;}
    
int k = 1, len, p = k + nx[k] - 1, x, y;
    re2(i, 
2, W) {
        len 
= nx[i - k];
        
if (i + len <= p) nx[i] = len; else {
            x 
= p + 1; y = p - i + 1if (y < 0) {x++; y = 0;}
            
for (; x<=&& ss0[x]==ss0[y]; x++, y++) ;
            nx[i] 
= y; k = i; p = i + y - 1;
        }
    }
    
int res0 = INF, tmp, V;
    re2(i, 
1, W) if (!(W % i) && nx[i] == W - i) {
        V 
= F[l][l + i - 1+ 2; tmp = W / i; while (tmp) {tmp /= 10; V++;}
        
if (W < V) V = W;
        
if (V < res0) res0 = V;
    }
    
return res0;
}
void solve()
{
    re(i, n) F[i][i] 
= 1;
    
int j, tmp;
    re2(x, 
1, n) re(i, n-x) {
        j 
= i + x; F[i][j] = sol0(i, j);
        re2(k, i, j) {tmp 
= F[i][k] + F[k + 1][j]; if (tmp < F[i][j]) F[i][j] = tmp;}
    }
    res 
= F[0][n - 1];
}
void pri()
{
    printf(
"%d\n", res);
}
int main()
{
    init();
    solve();
    pri();
    
return 0;
}

posted @ 2012-10-24 15:11 Mato_No1 阅读(516) | 评论 (0)编辑 收藏

原题地址
首先,看这么小的范围就知道,数学方法肯定搞不了……又想不到其它模型……只能用状压硬搞了囧……
问题是,5^15稳T,如果能倒过来,15^5,就不会T了。
可以发现,C值相同的颜色本质上是一样的……因此,只需要保存目前C值为1、2、3、4、5的颜色各有多少种就行了囧……(当然在过程中还会出现C值为0的,即用完的颜色,不过0、1、2、3、4、5的和是颜色总数,而且从下面可以看出,C值为0的确实“木有用”);
设F[s1][s2][s3][s4][s5][v]为涂完前若干个木块(这个个数可以通过s1~s5算出,不过我们并不需要它囧……)后,C值为1~5的颜色各有s1~s5种,且这若干个中的最后一个涂的颜色还剩的C值为v(显然0<=v<=4)。
边界:F[S[1]][S[2]][S[3]][S[4]][S[5]][0]=1,其余为0(S[i]为一开始C值为i的颜色种数)。
计算F时,前推后(注意顺序,是按照S[5]逆序最先,再依次是S[4]~S[1],都是逆序,v可任意定序),枚举下一个木块的颜色是现在还剩多少的,如果它与目前的这个(最后一个)剩的相同,则要减1,否则不减。具体的方程见代码。
注意细节:枚举F的s1~s5下标时,都要N(颜色总数)开始枚举,因为过程中某些s值会增加;

本题的启示就是,在设计状压DP的时候,如果正着来不行,可以反着来,或许就能设计出符合要求的解法。

代码:
#include <iostream>
#include 
<stdio.h>
#include 
<stdlib.h>
#include 
<string.h>
using namespace std;
#define re(i, n) for (int i=0; i<n; i++)
#define re1(i, n) for (int i=1; i<=n; i++)
#define re2(i, l, r) for (int i=l; i<r; i++)
#define re3(i, l, r) for (int i=l; i<=r; i++)
#define rre(i, n) for (int i=n-1; i>=0; i--)
#define rre1(i, n) for (int i=n; i>0; i--)
#define rre2(i, r, l) for (int i=r-1; i>=l; i--)
#define rre3(i, r, l) for (int i=r; i>=l; i--)
#define ll long long
const int n = 5, MAXM = 16, MOD = 1000000007;
int m, S[n + 1];
ll F[MAXM][MAXM][MAXM][MAXM][MAXM][n], res;
void init()
{
    scanf(
"%d"&m); int x;
    re(i, m) {scanf(
"%d"&x); S[x]++;}
}
void solve()
{
    F[S[
1]][S[2]][S[3]][S[4]][S[5]][0= 1int tmp;
    rre3(i5, m, 
0) rre3(i4, m, 0) rre3(i3, m, 0) rre3(i2, m, 0) rre3(i1, m, 0) re(v, n)
        
if (F[i1][i2][i3][i4][i5][v]) {
            
if (i1) {
                
if (v == 1) tmp = i1 - 1else tmp = i1;
                
if (tmp) {
                    F[i1 
- 1][i2][i3][i4][i5][0+= tmp * F[i1][i2][i3][i4][i5][v];
                    F[i1 
- 1][i2][i3][i4][i5][0%= MOD;
                }
            }
            
if (i2) {
                
if (v == 2) tmp = i2 - 1else tmp = i2;
                
if (tmp) {
                    F[i1 
+ 1][i2 - 1][i3][i4][i5][1+= tmp * F[i1][i2][i3][i4][i5][v];
                    F[i1 
+ 1][i2 - 1][i3][i4][i5][1%= MOD;
                }
            }
            
if (i3) {
                
if (v == 3) tmp = i3 - 1else tmp = i3;
                
if (tmp) {
                    F[i1][i2 
+ 1][i3 - 1][i4][i5][2+= tmp * F[i1][i2][i3][i4][i5][v];
                    F[i1][i2 
+ 1][i3 - 1][i4][i5][2%= MOD;
                }
            }
            
if (i4) {
                
if (v == 4) tmp = i4 - 1else tmp = i4;
                
if (tmp) {
                    F[i1][i2][i3 
+ 1][i4 - 1][i5][3+= tmp * F[i1][i2][i3][i4][i5][v];
                    F[i1][i2][i3 
+ 1][i4 - 1][i5][3%= MOD;
                }
            }
            
if (i5) {
                F[i1][i2][i3][i4 
+ 1][i5 - 1][4+= i5 * F[i1][i2][i3][i4][i5][v];
                F[i1][i2][i3][i4 
+ 1][i5 - 1][4%= MOD;
            }
        }
    res 
= F[0][0][0][0][0][0];
}
void pri()
{
    cout 
<< res << endl;
}
int main()
{
    init();
    solve();
    pri();
    
return 0;
}

posted @ 2012-10-24 14:59 Mato_No1 阅读(524) | 评论 (0)编辑 收藏

     摘要: [SCOI2005]栅栏 [SCOI2005]骑士精神 DFS优化类题目的代表。【栅栏】方法一:将N块目标木板的长度递增排序,然后,从前到后搜索每块目标木板从哪块原料中得到,直到所有的原料都不够用为止。优化:(1)启发函数:从目前的每块原料中,尝试依次切出目前剩余的最小长度的目标木板,则各块原料切出的块数之和就是一个乐观估计(比如剩余3块原料的长度为10、12、19,剩余的目标木板为3、4、5、6...  阅读全文

posted @ 2012-10-19 21:48 Mato_No1 阅读(1041) | 评论 (0)编辑 收藏

相关链接
插头DP拯救了这个世界……

赶快看插头DP的论文去……
(以后更新)

posted @ 2012-10-19 21:48 Mato_No1 阅读(373) | 评论 (0)编辑 收藏

一开始想傻了囧……不过很快就发现这其实是个超级大水题……
考虑斜堆中最后插入的那个结点,容易发现:
(1)它一定是一个极左结点(就是从根往它的路上一直都是沿着左链走),因为插入的时候每次都是插入到左子树中;
(2)它一定木有右子树,因为插入的时候每次都是把原来的某棵子树作为新结点的左子树;

满足(1)(2)的结点可能有多个,但紧接着可以发现,这个斜堆中的每个结点如果木有左子结点,那么也木有右子结点(或者说,每个非叶结点都有左子树),而在插入一个结点之前,其所有的祖先都被交换了左右子树,所以,若新结点的祖先中有满足(1)(2)的,且新结点不是叶结点,那么在新结点插入之前,这个满足(1)(2)的祖先必然是只有右子树而木有左子树的,这与上面的那个性质矛盾,所以,可以得出:最后插入的那个结点一定是满足(1)(2)的结点中,深度最小的那个(设为X),除非X的左子结点是叶结点,此时为了满足字典序最小,应该取X的左子结点为最后插入的。找到这个最后插入的结点以后,只需要把它删掉,并把它的所有祖先交换左右子树,就是插入该结点以前的状态了。这样可以找到字典序最小的插入顺序。
———————————————————————————————————————————————————
但是,这个题的意义还不止于此,必须要搞清楚斜堆到底是什么,有什么应用囧……

斜堆是可合并堆的一种实现形式,其更稳定的实现是左偏树(斜堆只能做到均摊logN,而左偏树则可以严格做到每次操作O(logN))。
斜堆最典型的特点,上面已经说过了,如果一个结点没有左子树,那么它也一定没有右子树。这样,大多数斜堆看上去是往左倾斜的(这也就是它的名字的由来……)。如果给每个结点加上一个距离值dist[],为该结点到它最近的没有右子树的子结点的距离,并且满足任意结点的左子结点的距离值都不小于右子结点的距离值的话,就成了左偏树囧……

可合并堆,顾名思义,它必须满足两个性质:(1)是堆,也就是每个结点的关键字都不大于(小顶堆)/不小于(大顶堆)其两个子结点的关键字;(2)它必须在O(logN)时间内完成合并操作,即将两个堆合并为一个,且合并成的堆仍满足原来的性质。
斜堆的合并操作有点像某些函数式数据结构,但它并不会动用额外的空间。该合并操作使用递归实现,设两个斜堆(小顶堆)的根结点为A、B,若A和B中的某一个为空,则返回另一个;若A和B均非空,则先将它们中关键字小的那个的右子树与关键字大的那个的整棵树合并,作为关键字小的那个的新的右子树,然后,如果是左偏树的话要更新dist,若dist不满足“左不小于右”,还要交换左右子树。

斜堆可以支持的操作有(指能在O(logN)时间内完成的操作):
(1)插入结点:(用合并实现);
(2)删除任意结点:(将待删除结点的两棵子树合并,取代原来的位置,若是左偏树的话还要往上更新dist直到dist不变为止,某论文里有证明,每次删除更新dist次数不会超过2logN);
(3)合并两个斜堆;
(4)找最小/大值;
(5)求以某个结点为根的子树大小(维护sz即可);

斜堆不能支持的操作有(指不能在O(logN)时间内完成的操作):
(1)查找任意结点。因此,若要删除某个指定结点,则必须先用下标等索引到它;
(2)找第K小(如果这个都能实现的话,斜堆就可以替代平衡树了囧……还是可合并平衡树……);
(3)找某个结点所在树的根结点(但是配合并查集+索引可以实现,详见HDU1512);

至于编程复杂度方面……非常非常好写!基本上一个合并操作就够了,<10行(斜堆的好写程度仅次于并查集和普通堆);
写的之后有三个主要的易疵点:
(1)合并的时候别忘了更新一些东东,尤其别忘了返回根结点;
(2)(极易疵的!!)如果要删除某个结点,必须把它的所有信息恢复到孤立结点的状态,即断开与原树的一切联系(pr、L、R全部置0),dist(如果是左偏树)置0、sz置1;(3)下标从1开始,0号结点作特殊用途(dist值为-1,sz值为0),如果某个结点的pr、L、R不存在则为0;

例题(由于想稳定,本沙茶全都是用左偏树写的囧):
【1】HDU1512
基本操作题,配合并查集+索引找根即可;
#include <iostream>
#include 
<stdio.h>
#include 
<stdlib.h>
#include 
<string.h>
using namespace std;
#define re(i, n) for (int i=0; i<n; i++)
#define re1(i, n) for (int i=1; i<=n; i++)
#define re2(i, l, r) for (int i=l; i<r; i++)
#define re3(i, l, r) for (int i=l; i<=r; i++)
#define rre(i, n) for (int i=n-1; i>=0; i--)
#define rre1(i, n) for (int i=n; i>0; i--)
#define rre2(i, r, l) for (int i=r-1; i>=l; i--)
#define rre3(i, r, l) for (int i=r; i>=l; i--)
#define ll long long
const int MAXN = 100010, INF = ~0U >> 2;
int n, u[MAXN], rt[MAXN], V[MAXN], dist[MAXN], pr[MAXN], L[MAXN], R[MAXN], res;
int UFS_find(int x)
{
    
int tmp = x, r = x; while (u[r] >= 0) r = u[r]; while (x != r) {tmp = u[x]; u[x] = r; x = tmp;} return r;
}
void UFS_union(int s1, int s2, int rt0)
{
    
if (u[s1] >= u[s2]) {u[s1] = s2; u[s2]--; rt[s2] = rt0;} else {u[s2] = s1; u[s1]--; rt[s1] = rt0;}
}
int heap_union(int s1, int s2)
{
    
if (!s1) return s2; else if (!s2) return s1; else if (V[s1] >= V[s2]) {
        
int z = heap_union(R[s1], s2);
        R[s1] 
= z; pr[z] = s1; if (dist[L[s1]] < dist[z]) {int tmp = L[s1]; L[s1] = R[s1]; R[s1] = tmp;}
        dist[s1] 
= dist[R[s1]] + 1return s1;
    } 
else {
        
int z = heap_union(s1, R[s2]);
        R[s2] 
= z; pr[z] = s2; if (dist[L[s2]] < dist[z]) {int tmp = L[s2]; L[s2] = R[s2]; R[s2] = tmp;}
        dist[s2] 
= dist[R[s2]] + 1return s2;
    }
}
void prepare()
{
    dist[
0= -1; re1(i, n) {u[i] = -1; rt[i] = i; dist[i] = pr[i] = L[i] = R[i] = 0;}
}
void solve(int x, int y)
{
    
int s1 = UFS_find(x), s2 = UFS_find(y); if (s1 == s2) {res = -1return;}
    
int rt1 = rt[s1], rt2 = rt[s2];
    
int z1 = heap_union(L[rt1], R[rt1]); L[rt1] = R[rt1] = pr[z1] = 0;
    V[rt1] 
/= 2; z1 = heap_union(rt1, z1); pr[z1] = 0;
    
int z2 = heap_union(L[rt2], R[rt2]); L[rt2] = R[rt2] = pr[z2] = 0;
    V[rt2] 
/= 2; z2 = heap_union(rt2, z2); pr[z2] = 0;
    
int z = heap_union(z1, z2); pr[z] = 0;
    UFS_union(s1, s2, z);
    res 
= V[z];
}
int main()
{
    
int m, x0, y0;
    
while (scanf("%d"&n) != EOF) {
        re1(i, n) scanf(
"%d"&V[i]); prepare();
        scanf(
"%d"&m);
        re(i, m) {
            scanf(
"%d%d"&x0, &y0);
            solve(x0, y0);
            printf(
"%d\n", res);
        }
    }
    
return 0;
}


【2】HDU3031
综合操作题,需要sz,同时也可以考察数据结构的综合应用能力。
#include <iostream>
#include 
<stdio.h>
#include 
<stdlib.h>
#include 
<string.h>
#include 
<algorithm>
using namespace std;
#define re(i, n) for (int i=0; i<n; i++)
#define re1(i, n) for (int i=1; i<=n; i++)
#define re2(i, l, r) for (int i=l; i<r; i++)
#define re3(i, l, r) for (int i=l; i<=r; i++)
#define rre(i, n) for (int i=n-1; i>=0; i--)
#define rre1(i, n) for (int i=n; i>0; i--)
#define rre2(i, r, l) for (int i=r-1; i>=l; i--)
#define rre3(i, r, l) for (int i=r; i>=l; i--)
#define ll long long
const int MAXN = 1000010, MAXM = 101, MAXLEN_M = 10010, INF = ~0U >> 2;
int n, m, len[MAXM], V0[MAXM][MAXLEN_M], root[2];
int V[MAXN], dist[MAXN], pr[MAXN], L[MAXN], R[MAXN], sz[MAXN];
bool FS;
void upd(int x)
{
    sz[x] 
= sz[L[x]] + sz[R[x]] + 1;
}
int heap_union(int s1, int s2)
{
    
if (!s1) return s2; else if (!s2) return s1; else if (V[s1] >= V[s2]) {
        
int s0 = heap_union(R[s1], s2);
        pr[s0] 
= s1; R[s1] = s0; if (dist[L[s1]] < dist[s0]) {int tmp = L[s1]; L[s1] = R[s1]; R[s1] = tmp;} dist[s1] = dist[R[s1]] + 1; upd(s1);
        
return s1;
    } 
else {
        
int s0 = heap_union(s1, R[s2]);
        pr[s0] 
= s2; R[s2] = s0; if (dist[L[s2]] < dist[s0]) {int tmp = L[s2]; L[s2] = R[s2]; R[s2] = tmp;} dist[s2] = dist[R[s2]] + 1; upd(s2);
        
return s2;
    }
}
void opr_T(int x)
{
    sort(V0[x], V0[x] 
+ len[x]); int root0 = n + 1;
    rre(i, len[x]) {
        n
++if (i == len[x] - 1) pr[n] = 0else pr[n] = n - 1if (i) L[n] = n + 1else L[n] = 0; R[n] = dist[n] = 0; V[n] = V0[x][i]; sz[n] = i + 1;
    }
    root[FS] 
= heap_union(root[FS], root0);
}
void opr_A(int x)
{
    V[root[FS]] 
+= x;
}
void opr_E(int x)
{
    
int root0 = root[FS], z0; pr[z0 = heap_union(L[root0], R[root0])] = 0; L[root0] = R[root0] = dist[root0] = 0; sz[root0] = 1; V[root0] = x;
    root[FS] 
= heap_union(z0, root0);
}
void opr_L()
{
    
int root0 = root[FS], z0; pr[z0 = heap_union(L[root0], R[root0])] = 0; L[root0] = R[root0] = dist[root0] = 0; sz[root0] = 1;
}
void opr_C()
{
    
int root0 = root[0], root1 = root[1];
    
if (V[root0] > V[root1]) {
        root[
0= heap_union(root0, root1); root[1= 0;
    } 
else if (V[root0] < V[root1]) {
        root[
1= heap_union(root0, root1); root[0= 0;
    }
}
int main()
{
    
int tests, sc0 = 0, sc1 = 0, P, tmp; char ssss[10];
    scanf(
"%d"&tests);
    re(testno, tests) {
        scanf(
"%d%d"&P, &m);
        re(i, m) scanf(
"%d"&len[i]);
        re(i, m) re(j, len[i]) scanf(
"%d"&V0[i][j]); n = root[0= root[1= 0; dist[0= -1; sz[0= 0; FS = 0;
        re(i, P) {
            scanf(
"%s", ssss);
            
if (ssss[0== 'T') {scanf("%d"&tmp); opr_T(--tmp);}
            
else if (ssss[0== 'A') {scanf("%d"&tmp); opr_A(tmp);}
            
else if (ssss[0== 'E') {scanf("%d"&tmp); opr_E(tmp);}
            
else if (ssss[0== 'L') opr_L(); else opr_C();
            FS 
= !FS;
        }
        printf(
"%d:%d\n", sz[root[0]], sz[root[1]]);
        
if (sz[root[0]] >= sz[root[1]]) sc0++else sc1++;
    }
    
if (sc0 > sc1) puts("HahahaI win!!"); else puts("I will be back!!");
    
return 0;
}

posted @ 2012-10-07 11:02 Mato_No1 阅读(3016) | 评论 (1)编辑 收藏

仅列出标题
共12页: 1 2 3 4 5 6 7 8 9 Last