摘要: 维护两个字符串,操作一可以将其中一个字符串的一个字符进行修改,操作二是查询从某一位开始的最长公共串。 这题比较简单,只要维护一个数组,0表示两个字符串该位字符相同,1表示两个字符串该位字符不同。用树状数组维护前缀和,用sum(i)表示前i个元素的和,如果要查询从第i位开始的最长公共串,只要求满足sum(x)-sum(i)==0的最大x即可,二分去找这个x就行了。复杂度比线段树去做多一个二分的log(N),但是线段树常数比树状数组大不少,所以实际效率是差不多的,而且代码要好写很多。 1 #include <stdio.h> 2 #include <string.h> 3 阅读全文
posted @ 2012-08-29 19:50 Burn_E 阅读(251) 评论(0) 推荐(0)
摘要: 题目大意是说给你一个起点和终点,一个人要从起点走到终点,它不能经过一个点两次,问他不可能经过哪些点。 显然转化成能经过哪些点要好想一些,用N减去能经过的点就可以得到答案。下面的讨论都是基于求他可能经过的点有多少个。 很容易想到用双联通分量,但是建图确实比较麻烦。如下图,一个人想要从1走到3,那它可能在的点就是1,2,3。因为2是一个割点,它如果从2走到了4,想要到达3就必须再经过2,所以可以用割点和双联通建图。 用割点和双联通可以建成双联通与割点相邻的图,若右图所示。可以证明这是一棵树,因为如果存在环,这个环必然可以缩成一个点,树中任意两点有且仅有一条路径,于是只要统计这条路径上有一... 阅读全文
posted @ 2012-08-29 19:32 Burn_E 阅读(716) 评论(0) 推荐(0)
摘要: 题目基于一个定理:当所有点相连的点的个数大于N/2时,一定可以构造出一条哈密顿回路,构造的复杂度是N^2。 这题的正解是构造,但很多人都是搜索过的,只能说明这题的数据比较水。sgu上有一道基本一样的题目(sgu122),这一题不用构造是过不了的。 至于构造方法,也就是3步。 STEP1:先找两个相邻点s-t,扩充出一条链直到到不能扩充为止。 STEP2:这时如果s-t不相邻,在链上找一点vi满足s与next[vi]相邻并且vi与t相邻,链转化为s-vi-t-next[vi]-s,根据鸽巢原理这个点必然存在。 STEP3:如果链中的点不足N个,就在环上开一个新口继续加点,重复STE... 阅读全文
posted @ 2012-08-29 02:15 Burn_E 阅读(362) 评论(0) 推荐(0)
摘要: 题解说是容斥原理,彻底没看懂,搜到的题解也是各种简洁,就提到是容斥原理,难道大家的数学都这么好,一眼就看懂了。。。。 这题也可以用概率DP做,相比之下这种做法要容易理解的多。用一个状态表示当前抽到的卡片的状况,1代表尚未拿的卡片,有d[now]=x*d[now]+sigma(si*pi*(now^(1<<i)))+1,si表示stat中该位是0还是1,x表示停留在该状态的概率,即没拿到其它卡片的概率(没抽到卡片+抽到当前已有卡片),移项可以得到d[now]=sigma(..)/(1-x)。 1 #include <string.h> 2 #include <std 阅读全文
posted @ 2012-08-29 01:56 Burn_E 阅读(232) 评论(0) 推荐(0)
摘要: 这就是大神口中的简单题,我的数论简直烂到不行,这些数学出身的家伙何必出这些恶心的数学题来难为我们呢。。 用到一个公式 A^x%P=(A^(x%phi(P)+phi[P]))%P (x>=phi[C]),phi[C]表示欧拉函数。 注意条件是x>=phi[C],但这题的x是增长很快的,很快就能满足这个条件,所以x<phi[C]这部分暴力即可。 接着继续暴力求x%phi[C]!=0的情况,很快就会出现x%phi[C]==0,并且之后一直都会满足,题目转化为求A^phi[P]%P==b,根据鸽巢原理,一定会出现长度为P循环节,于是统计循环节内满足条件的数的个数,再乘以循环节个数,然 阅读全文
posted @ 2012-08-29 01:48 Burn_E 阅读(231) 评论(0) 推荐(0)
摘要: 很老的题了,一开始懒的写HASH写个二分查找还没过,后来改成HASH就A了。。 1 #include <stdio.h> 2 #include <string.h> 3 #define MOD 999997 4 #define PRI 199 5 typedef __int64 LL; 6 LL add=10000000000000000LL; 7 int cas,n; 8 LL d[5][201]; 9 LL num[MOD];10 int first[MOD],next[MOD/2],es;11 void ins(LL x,int p){12 num[es]=x,n 阅读全文
posted @ 2012-08-29 01:38 Burn_E 阅读(159) 评论(0) 推荐(0)
摘要: 其实是很裸的一道题,可能是因为几乎没用过扩展KMP,只想到用后缀数组,但这题的常数卡的很厉害,不用扩展KMP应该是过不了的。 扩展KMP能求出一个串所有后缀串(即s[i...len])和模式串的最长公共前缀。于是只要将这个串复制一遍,求出该串每个后缀与其本身的最长公共前缀即可,当公共前缀>=len时,显然相等,否则只要比较下一位就能确定这个串与原串的大小关系。 至于重复串的问题,只有当这个串有循环节的时候才会产生重复串,用KMP的next数组求出最小循环节,用长度除以最小循环节得到循环节个数,在将3个答案都除以循环节个数即可。 1 #include <string.h> 2 阅读全文
posted @ 2012-08-29 01:36 Burn_E 阅读(310) 评论(0) 推荐(0)
摘要: 烟囱是一个3*3的中空构造,给定烟囱的高度,问用1*1*2的砖头搭成这个烟囱有多少种方法。 首先用一个8位二进制数表示某一层的状态。枚举上下两层的状态,判断这两个状态是否可以相邻,上一层必须将下层填满,但是上层自身可以有空格。当下层为0时,上层必须为1,表示放一个竖着的矩形块,因此必须满足up_stat|low_stat=255,上层中除了竖着的砖头,都是单个或连续个横放的砖头,所以必须满足up_stat&low_stat中的连续1都是偶数个。注意循环的问题,比如0的位置是1,7位置也是1,而实际上0和7是相邻着的。 相邻层的状态会构造出一个矩阵表示转化关系,为0时代表不能相邻... 阅读全文
posted @ 2012-08-29 01:22 Burn_E 阅读(317) 评论(0) 推荐(0)
摘要: 首先能够构成正方形的两个对顶点肯定在同一条对角线上,可以想到依次处理每条对角线上的点。 对于每个点,预处理出它能到的四个方向的连续1最多有多少个,记为p_up,p_down,p_left,p_right,显然,决定某一个点向右下能延伸的多少只取决于p_down和p_right中的较小值,决定某一个点向左上能延伸到多少只取决于p_up和p_left的较小值。 对于每个点,记录它能到达的最右的x轴的绝对坐标,并记录它自身的y坐标。 统计一个点和它左上的点(在对角线上)能组成多少个正方形时,只要判断有多少个点向右能和它相交即可。比如统计5,只要记录1~4中有多少点向右能和红线交叉,显然... 阅读全文
posted @ 2012-08-29 01:03 Burn_E 阅读(331) 评论(0) 推荐(0)