07 2012 档案
摘要:首先申明此方法POJ超时,HDU压线过,优化版见http://www.cnblogs.com/Lyush/archive/2012/07/28/2613516.html线段树的写法与上面链接中的离散化版本的想法是相近的,只不过这里仅仅是通过线段树来保留某一x区域的多个矩形的面积并。代码如下:#include <cstdlib>#include <cstring>#include <cstdio>#include <map>#include <algorithm>using namespace std;int N, M, Q, cnt;
阅读全文
摘要:这题首先要将等式两边除以k,这样在求两边的互质数的个数就是最后的结果了。我们采用的策略就是用小区间的每一个数去匹配大区间的数。但是如果每次都去分解一个数的质因子的话,那么会TLE,因此先预处理出1-100000每个数的质因子再进行计算。代码如下:#include <cstring>#include <cstdlib>#include <cstdio>#include <algorithm>#include <cmath>using namespace std;int a, b, c, d, k, rec[300000], idx;in
阅读全文
摘要:将与N不互质的数全部找出来,再应用容斥定理求得最后的结果。这题在求 a/b MOD c 的时候使用费马小定理等价于 a*b^c(-2) MOD c.用x/lnx 可以估计出大概有多少素数。代码如下:#include <cstdlib>#include <cstdio>#include <cstring>#include <cmath>#include <algorithm>#define MOD 1000000007LLusing namespace std;typedef long long int Int64;typedef lo
阅读全文
摘要:这题简单说就是求矩形的面积并,线段树?只有20个矩形,我们可以用容斥来做。但是这个有个比较麻烦的地方就是要求出任意组合情况下的面积并,试过几次每次进行求解的写法都一一超时了。这里选择在dfs的时候直接枚举题目将询问的状态,只要当前状态是其子集的话,就直接加到上面。最后M次询问就能够在O(1)的时间内完成了。296MS水过了。代码如下:#include <cstring>#include <cstdlib>#include <cstdio>#include <algorithm>#define INF 10000using namespace st
阅读全文
摘要:红果果的容斥定理。代码如下:#include <cstdlib>#include <cstring>#include <cstdio>#include <algorithm>using namespace std;int ans, seq[15], N, flag;int M;inline int GCD(int a, int b){ int t; while (b) { t = a; a = b; b = t % b; } return a;}inline int LCM(int a, int b) { return a...
阅读全文
摘要:该题就是给定一个数,求某个区间内有多少数与这个数互质。首先我们要明确,对于一个给定的区间,我们如果能够求出这个区间内所有与其不互质的数的个数的话,那么互质数的个数也就求出来。这个叫做反面求解。对于任何一个正整数N,都有其唯一的素因子分解形式,我们可以这样想,任何与N不互质的数一定是其某一个质因子的倍数,所以我们通过某一个质因子能够确定一个范围内的有多少个数该质因子的倍数的数。但是这并不是所有不互质数的充分条件,对于另外的质因子同样满足能够确定一系列的数,我们要做的就是融过容斥定理求他们的并集。代码如下:#include <cstdlib>#include <cstring&g
阅读全文
摘要:这题也算是技巧性较强的一题,这题与上一题HDU-4311唯一的不同分出了八个方向,而且这八个方向没有上题那么和谐了,有四个方向的曼哈顿距离不再是1,也就是说题中所给定的逻辑距离在曼哈顿距离上没有了的体现,不过如果你数学素养好的话,有一个距离叫做切比雪夫距离 D = max(|x1-x2|, |y1-y2|),可以发现虽然曼哈顿距离有了改变,但是切比雪夫还是帮助我们找到了共同点,因为从一个点到另外一个点我们始终会先选择走斜线,一单位斜线相距离当于两单位曼哈顿距离,之所以只取最大值,是因为小的一部分曼哈顿距离我们可以通过斜线来消掉。如果数据量不大的话,我们就可以根据这个方法直接暴力了,但这好像对这
阅读全文
摘要:该题题义是给定如下一个方程组:F(1) = C1 (mod) PF(2) = C2 (mod) PF(3) = C3 (mod) P ...其中F(1) = A(1,1)*x1 + A(1, 2)*x2 + A(1, 3)*x3...其中A(i, j) = i ^ (j-1).面对这样一个方程,我们的做法就是先不管方程右端的(mod)P,因为F(i) 和 Ci 是同余的,那么在方程两端乘以一个数是没有影响的,代入某一个方程同样是允许的。于是剩下的就是高斯消元。由于解是唯一的,因此解出来的系数矩阵一定是满秩。接下来就可一用扩展gcd求解未知元了。代码如下:#include <cstdlib
阅读全文
摘要:该题就是考的是如何花最小的代价使得一棵树划分开且不含后同类节点。我们将边按从大到小的顺序排好序,然后就是看是否这条边能够使得两个同类的节点连在一起,如果能够的话,那么这条边就是我们要选择的划分边。首先将特征值保留起来,并通过并查集扩充给标记点。代码如下:#include <cstring>#include <cstdlib>#include <cstdio>#include <map>#include <algorithm>using namespace std;int N, M, set[100005], have[100005];
阅读全文
摘要:这题在比赛的时候没做出来实在是不应该。本来也是用对数处理的,但是后面写的七零八落的。这题也可以直接求,记录每个点最少消耗的流量,剩余流量为初始流量减去这个值,逐步向下迭代。当然这里可以去求他的剩余值,根据公式 最后的流量 L = I * (1-p1) * (1-p2) * ... * (1-pn) 我们对两边同时取对数的话,那么我们就将乘法化成了加法,并且直接求一个最长路就可以了。最后再拿总流量减去最大的剩余量即可。代码如下:#include <cstdio>#include <cstring>#include <cstdlib>#include <q
阅读全文
摘要:该题具有一定的技巧性,需要在Nlog(N)的时间复杂度下计算出任意一个点,N-1个点到其的距离综和,这里需要运用这样一个技巧,将x,y分开计算,首先计算x轴的距离,那么就先排一次序,然后有到P号点的距离和为 (P-1) * Xp - sum(X1...Xp-1) + sum(Xp+1...Xn) - (N-P) * xp; 同理可计算出y轴的距离,这两个距离是累加到一个结构体上的。所以最后直接找最小值即可。代码如下:#include <cstdlib>#include <cstring>#include <cstdio>#include <cmath&
阅读全文
摘要:这题用贪心是很容易过的,直接先杀死对方单位时间输出较高的对象。这题的动态规划解是将N个敌人压缩到一个int数里面,dp[j] 表示在剩余了j这个数里面所蕴含的敌人的情况下的最大扣血量。dp方程为 dp[s] = min( dp[s - {bit}] + sumdps[s] * h[bit] ) 其中bit枚举每一位。代码如下:#include <cstdlib>#include <cstring>#include <cstdio>#include <algorithm>using namespace std;int dp[1200000], N,
阅读全文
摘要:代码如下:#include <cstdlib>#include <cstring>#include <cstdio>#include <algorithm>#define TO(x, y) (x-1)*N+yusing namespace std;char G[30][30];int dir[4][2] = {1, 0, -1, 0, 0, 1, 0, -1}, N;int C;inline bool judge(int x, int y){ if (x < 1 || x > N || y < 1 || y > N) {
阅读全文
摘要:这题我们可以参考开关那题,只不过这里是求最少的操作次数,那么我们需要对变元进行枚举,算出所有的情况下,最少需要改变的次数。代码如下:#include <cstdlib>#include <cstring>#include <cstdio>#include <algorithm>#define TO(x, y) (x-1)*4+yusing namespace std;char G[6][6];int dir[4][2] = {1, 0, -1, 0, 0, 1, 0, -1};inline bool judge(int x, int y){ if
阅读全文
摘要:这题是给定N个灯的初始和最终状态,再给定一些关系,这些关系说明按某个开关可能影响其他的灯的开关情况,可以将这种关系视为一种取反的关系。对于这题我们假设一组数据:30 1 01 1 01 22 31 33 20 0对于以上的数据,我们用矩阵来表示整个操作的过程和状态 0 1S = 1 E = 1 0 0我们可以很显然的知道,某个等的亮灭情况将体现出各个开关的复合结果,因此我们可以得到这样的方程组,模二加等价于异或操作:E(a) = xa*A11 ^ xb*A12 ^ xc*A13 ^ S(a);E(b) = xa*A21 ^ xb*A22 ...
阅读全文
摘要:一个需要进行转化的题目。x = (n*(n+k))/k = n*n/k + n,最后求小于等于N且是N^2的因子的数的个数。代码如下:#include <cstdlib>#include <cstdio>#include <cstring>#include <cmath>#include <map>using namespace std;int N;map<int,int>mp;map<int,int>::iterator it;int fun(){ int ret = 1; for (it = mp.begi
阅读全文
摘要:简单的快速矩阵幂:Fn 1 1 Fn-1 = * Fn-1 1 0 Fn-2把前面的矩阵作快速幂就可以了。代码如下:#include <cstdlib>#include <cstdio>#include <cstring>#include <algorithm>#define MOD 10000using namespace std;struct Matrix // ['meitriks]{ int a[2][2]; void New (int x, int y, int z, int w) { a[0][0] ...
阅读全文
摘要:该题与上题相比增加了多种分法,而不只是四条边,问题是最多能够分成多少条边。上题代码其实错了(已改),但是也过了,这题改的还纠结。代码如下:#include <cstdlib>#include <cstdio>#include <cstring>#include <algorithm>using namespace std;int N, seq[100], mode, use[100], flag;void dfs(int cap, int last, int num){ if (num == N) { flag = 1; return; } if
阅读全文
摘要:该题问给定的棍子能否组成一个正方形。首先我们要判定是否总长度是4的倍数,然后再决定是否存在某条边大于组合边长。搜索的过程中也是可以进行剪枝了。首先将边排序,我们可以假定所有的组合边由大小递减的边组成,那么我们在搜索的时候就不用再往前找边了。其次我们可以确定任何一条边都一定在一条组合边中,那么当我们以任意一条边开搜的情况下无解的话,那么我们就可以直接返回no了。最后在搜索某条边无解的情况下,我们可以把相同大小的边略过,因为前面相同长度的边都无法安排出一种方案,在少一条相同边情况下肯定也就无法给出安排了。代码如下:#include <cstdlib>#include <cstdi
阅读全文
摘要:该题题义是有一个显示器,在给定了一系列的操作后,询问最后显示器所显示的区域。对于每个操作,给定一个x坐标和一个y坐标,以及三角形(等腰直角三角形)的边长。对于每个面积覆盖次数为奇数的区域是显示的,对于覆盖了0次或偶数次的区域是不显示的。那么我们可以将题目这样进行转化,我们规定了个三角形的区域,它的横纵坐标分别是x, y,边长为 r 那么这个三角形可以用一个方程组来表示,令 ci = xi + yi + r, x + y <= ci; x >= xi; y >= yi;这个图形画出来就是一个三角形区域,对于后面进来的三角形,我们同样可以写出这样一个方程,我们需要解出这两个方程组
阅读全文
摘要:这个题在于唯一确定好色子的状态,其实只要知道了色子的前上右分别的点数,也就唯一确定了色子的状态,我们可以根据这三个状态来恢复整个色子的六个面的情况。这题还要注意对4进行取模(由于本身已经占了一个格子,因此要减1),直接模拟的话很有可能超时,利用switch的贯穿性质可以让我们的代码过程更加舒适。代码如下:#include <cstdlib>#include <cstdio>#include <cstring>#include <algorithm>using namespace std;int N, M, ti;long long int sum
阅读全文
摘要:这题竟然用java也可以过,因该算是最简单的吧了。当然另外的两重for循环的写法也算是很简单的了。这里就直接写素因子分解的写法。对于A中的数,我们可以将每个数都进行素因子分解,最后保留各个质数的指数,对B进行同样操作,然后在去两者指数的min值就可以了。这里要对大质数进行特殊处理。代码如下:#include <cstdlib>#include <cstdio>#include <cstring>#include <algorithm>#include <map>#define MOD 1000000000using namespace
阅读全文
摘要:算出每个窗户左上角和右下角的坐标,直接模拟就行了。这题直接把sum放在G数组后面,导致sum变成了char型,错了一次,G数组第一次只开了105~~~。代码如下:#include <cstring>#include <cstdio>#include <cstdlib>using namespace std;char G[600][600];int sum[10];int main(){ int N, M, x1, y1, x2, y2, cnt; while (scanf("%d %d", &N, &M) == 2) {
阅读全文
摘要:这题直接二分就可以了,注意下二分的返回值,以后都最好手动模拟一下。代码如下:#include <cstdlib>#include <cstdio>#include <cstring>#include <algorithm>using namespace std;typedef long long int Int64;Int64 N, M, seq[1000005];Int64 sum(Int64 h){ Int64 ret = 0; for (int i = 1; i <= N; ++i) { if (seq[i] > h) { re
阅读全文
摘要:这题用也算是贪心吧,不过这里有一点数学思想。对于要取掉K位的N位数,那么我们留下来的就是N-K位,我们不妨设 T = N - K; 那么我们选择的第一位数的后面就一定要有T-1个数让我们来选,因此第一个数的选择范围就是[1, N-T+1],当我们选取了第一个数后(假设位置为P),我们第二个数的选择范围就是 [P+1, N-T-2]了,一次类推。由于我们要取的是最大的数,所以我们每次都选取区间内的最大值,用线段树来作优化就可以了。代码如下:#include <cstdlib>#include <cstring>#include <cstdio>#include
阅读全文
摘要:对于一个串,我们可以这样考虑,首先我们从串的最后面开始向前遍历。对于一个串是 "XXXXAA",那么对于后面这两个A,我们是不用做任何考虑的,我们甚至可以直接认为这个串没有后面这两位。对于一个串是 "XXXXBB",那么我们是一定要选择反转的,因为单次操作的话将这两个(或者多个)B变成A需要两次操作,而我们通过翻转整个串,再翻转前N-2个串同样可以达到这个效果。但是我们翻转整个串可能为前面的字符串改变作了贡献。对于一个串是 "XXXXAB",那么我们是一定进行单个字符替换的。我们可以这样考虑,如果我们通过一次翻转操作来改变最后面的这一
阅读全文
摘要:这题数据范围小,就直接暴力了,没什么好讨论的了。代码如下:#include <cstdlib>#include <cstring>#include <cstdio>#include <algorithm>using namespace std;int N, M, seq[150];int main(){ int ret; while (scanf("%d %d", &N, &M) == 2) { ret = 0; for (int i = 1; i <= N; ++i) { scanf("%d&
阅读全文
摘要:这题是一道非常直接的中国剩余定理的题目,但是这里的不同的给定的几个数不一定是互质的。因此也就不能直接用解中国剩余定理的方法来求了。我们通过迭代法来求解最后的答案。设有 x = 1(mod 5) y = 2(mod 6) z = 3(mod 7)那么根据第一个方程我们设 x = 5t+1, 代入到第二个方程 5t+1 = 2(mod 6) ==> 5t -6u = 2-1 左边这个式子就可以用扩展GCD求出t的解,我们知道t的解由两部分组成,一部分是我们解出来的一般解5(必须保证为最小的正整数),此时u等于4,另外的就是加上 k 个 6 / gcd(5, 6)了,那么我们可以得到 t =.
阅读全文
摘要:这题就是一个简单扩展GCD,方程为 x*C + y * 2^k = B-A.代码如下:#include <cstdlib>#include <cstdio>#include <cstring>#include <iostream>using namespace std;typedef long long int Int64;Int64 A, B, C, K;Int64 _pow(Int64 a, Int64 b){ Int64 ret = 1; while (b) { if (b & 1) { ret *= a; } ...
阅读全文
摘要:中国剩余定理说白了就是小学时候的韩信点兵的完全版。给定一系列数,给定条件是一个数MOD这一些列数的结果,问你最后这个数最少为多少。抽象出来就是N个同余方程,利用扩展GCD就可以求得这一结果,本题给定的数都是互质的,因此处理起来就简单了。代码如下:#include <cstdlib>#include <cstdio>#include <cstring>using namespace std;int b[4], D;int ext_gcd(int a, int b, int &x, int &y){ int ret, temp; if (b ==
阅读全文
摘要:该题说的是一个小东西生活在管道内,长度为L,里面有一些蛋糕,现在动态的给定蛋糕的坐标,小东西的坐标初始话为0,当指令为吃蛋糕的时候,小东西将会去吃最临近的蛋糕。现在问你小东西在Q次询问下要走多远的距离。这题用树状数组+二分查找超时了。。 构造出一棵线段树,每个节点保留区间中所有的蛋糕数以及左右蛋糕最近的坐标。维护好线段树即可。代码如下:#include <cstdlib>#include <cstdio>#include <cstring>using namespace std;int L, Q;struct Node{ int num, l, r, lef
阅读全文
摘要:该题题义是给定一个公司的结构,然后针对每个员工的一系列操作。由于问题牵涉到一个员工以及一个员工所领导的部门,因此用普通线性结构显然效率太低。这里用到了线段树。step1:首先我们要确定题目是要对给定的点或者是区间进行操作,那么我们自然而然会想到线段树,但是这题还不是直接的线段树,需要对题中给定的关系进行离散话,也就是按 照先序或者是后序遍历进行排序,这样某一个员工所领导的部门下的成员就在物理上连续了,并且我们用两个数组分别记录某个成员所领导的部门的左边界和右边界。step2:有了上一步的操作后,我们就可以进行构树了,按照普通的线段树进行构建,线段树仅仅只是我们处理点和区间的一种数据结构,...
阅读全文
摘要:该题题意是给定一个音乐串,要求最长的主题串满足可以找到两个这样的串,在对方的每一位添加一个数字 两个串互相不能够有重叠有是多项式插值取模的hash的应用代码如下:#include <cstdlib>#include <cstring>#include <cstdio>#define T 99991#define MAXN 20000#define MOD 3001using namespace std;typedef unsigned long long UInt64;struct Node{ UInt64 key; int begin, end, next
阅读全文
摘要:这题的题意是给定N个串,某个串的子串在超过一半的串存在的话,那么这个串就是可取的,问满足这样的子串的最长长度是多少,如果有多个的话,按字典序输出。这题我是用hash过的。大体步骤是这样的,首先保留最长串的长度,然后二分0-MAXNLEN得到答案,那么这里重点就是如何去写这个判定函数。二分里面只会传递一个参数那就是长度K,根据这个长度我们把所有的串都拆成长度为K的子串,这里有个优化就是使用一种hash规则能够在得到1 - N的hash的时候计算出2 - N+1的hash值,那么这里用到了经典的多项式插值取模的方法:假设有一个字符串a[0],a[1],a[2],a[4],取长度为3的子串的时候,第
阅读全文
摘要:直接用DP方程直接TLE了,因为数据范围达到了10^9......这题的正解是先用DP方程分别求出在t步走到每一行(列)的可能,再将其相加到一个步数为t的数组中,表示到第t步时,所有行(列)的种数,最后再用一个组合公式,将规定的K步进行分解来求得最后的答案。这题要特别要注意边界条件,还有就是防止溢出。这里用到了一个公式来求组合数 C[i, j] = C[i-1, j] + C[i-1, j-1]。代码如下:#include <cstdlib>#include <cstdio>#include <cstring>#define MOD 1000000007us
阅读全文
摘要:这题有个技巧就是保留前缀和后缀级,然后利用公式 a*b MOD c = ( a MOD c * b MOD c ) MOD c。代码如下:#include <cstdlib>#include <cstdio>#include <cstring>#include <cmath>#include <algorithm>#define MOD 1000000007using namespace std;int N;long long a[100005], l[100005], r[100005];int main(){ while (sca
阅读全文
摘要:先生成蛇型矩阵,然后再筛选出素数进行标记,最后bfs。这里要注意题目要求的1-10000的之间的数路径,但是并不代表我们只要打印到这个范围的素数,因为很可能边沿的点需要走到外面的图形来完成对短路,外围的也不要打印太多,毕竟素数的个数越到外面是越稀疏的,所以打印到40000足矣。代码如下:#include <cstdlib>#include <cstring>#include <cstdio>#include <algorithm>#include <map>#define MAXN 40000using namespace std;i
阅读全文
摘要:首先将7种方块拆成19种方块,然后在进行dfs组合,当然如果给定的N*M不是4的倍数的时候记得直接输出0。代码如下:#include <cstdlib>#include <cstring>#include <cstdio>using namespace std;int N, M, ans, END, G[35][35], many[20];int mp[20] = {1, 1, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 7, 7};char ss[50][6][6] = { { "####"
阅读全文
摘要:该题题意就是求一个数最多能够开多少次方,这其中包含有负数,而且要用long long 型数据读入。首先将这个数的素因子分解求出,统计出它们的各自的个数,然后对它们的个数求一个gcd,最后输出。如果是正数的话直接输出,如果是负数的话需要将其的最大奇因子求出。代码如下:#include <cstdlib>#include <cstring>#include <cstdio>#include <algorithm>#include <cmath>using namespace std;int p[66000], cnt;long long
阅读全文
摘要:问你一个数在一个连续区间,这个区间全为和数的长度。代码如下:#include <cstring>#include <cstdio>#include <cstdlib>#include <algorithm>#define MAXN 1300000using namespace std;int p[MAXN+5], rec[100005], N;void pre(){ int k; for (int i = 4; i <= MAXN; i += 2) { p[i] = 1; } for (int i = 3; i <= 1141; i
阅读全文
摘要:代码如下:#include <cstdlib>#include <cstring>#include <cmath>#include <cstdio>using namespace std;int p[40010], a[10000], b[10000];void pre(){ for (int i = 4; i <= 40010; i += 2) { p[i] = 1; } for (int i = 3; i <= 200; i += 2) { if (!p[i]) { int k = 2 * i; fo...
阅读全文
摘要:筛出素数然后直接暴力即可。代码如下:#include <cstdlib>#include <cstring>#include <cstdio>#define MAXN 10000using namespace std;int N, M, d, p[600005];int hash[10005], path[10005];void pre(){ int k; for (int i = 4; i <= MAXN; i += 2) { p[i] = 1; } for (int i = 3; i <= 105; i += 2) { if (!...
阅读全文
摘要:跟杭电的奇怪的楼梯非常想。代码如下:#include <cstdio>#include <queue>using namespace std;struct Node{ int x, t;}e[100005], pos;int N, K, front, tail, hash[100005];void getnewpos(int x, int a[]){ a[0] = x - 1; a[1] = x + 1; a[2] = x << 1; }int bfs(){ memset(hash, 0, sizeof (hash)); hash[N] = 1; ...
阅读全文
摘要:就是将普通的二维推广到三维,方向变成了六个。代码如下:#include <cstring>#include <cstdio>#include <cstdlib>using namespace std;int L, N, M, sx, sy, sz; struct Node{ int x, y, z, t; }e[100005], pos;int front, tail, dir[6][3] ={ 0, 1, 0, 0, -1, 0, 1, 0, 0, -1, 0, 0, 0, 0, 1, 0, 0, -1}; // 六个方向,三个坐标 cha...
阅读全文
摘要:非常简单的一道搜索题,用状态压缩加DP写了一上午,写道后面越来越感觉这题状态压缩没有什么优势,每一行都与前面的行的排列有关系,因此不能够记忆化,没算完一次要把状态清空,可惜到最后还是错了。干脆直接暴力搜索。就这样过了。代码如下:#include <cstring>#include <cstdlib>#include <cstdio>#include <algorithm>using namespace std;int N, K, hash_x[10], hash_y[10], ans;char G[10][10];void dfs(int x,
阅读全文
摘要:之前有听说如果在一个迷宫中一直沿着某一堵墙走的话,那么一定可以走出这个迷宫,这题讲的就是这个内容。这题的问法比较奇怪,问你沿着左边的墙,右边的墙走所花的时间和最少所花的时间。该题难点就在与如何让dfs的时候能够沿着墙走。其实是有规律的,那就是往左边走是顺时针方向dfs,往右走逆时针方向走dfs,每次要确定上一次来的方向,这样能够确定你第一次试探的方向是那个方向。例如:如果从最左边的墙进入的话,那么首先选择往上走,否则向前走,再否则向下走,最后还是没法走的话就向左走(往回走),走了之后就直接return,每次走了之后绝对不会再换方向搜索。这题竟然错在了手写的找最短路的队列上。代码如下:#in..
阅读全文
摘要:简单的dfs搜索,题目要求是骑士可以从任意一点出发走完整个棋盘的路径。字典序输出要注意八个方向的排列顺序。代码如下:#include <cstring>#include <cstdlib>#include <cstdio>using namespace std;int N, M, dir[8][2] = {-2, -1, -2, 1, -1, -2, -1, 2, 1, -2, 1, 2, 2, -1, 2, 1};int visit[10][10], rec[100][2];bool judge(int x, int y){ if (x < 1 ||
阅读全文
摘要:这题用map就超时了,所以用字典树来优化,第一次写静态的,现在都不习惯用指针了。由于这里不要回到源点,所以不许要所有点的度都为偶数,零个或者两个均可,图也必须是连通的。代码如下:#include <cstring>#include <cstdlib>#include <cstdio>#include <string>using namespace std;char s1[15], s2[15];int idx = 0, flag = 0, ptr = 1;int set[2500005];struct Node{ int cnt, No; int
阅读全文
摘要:这题用hash表做有点无病呻吟了,因为用map更快更简单。把字符串按每一位乘以相应的位置,再进行hash操作。这题还做的时候还遇到一个问题,在进行字符串复制的时候,由于直接sizeof(in)由于in在这个函数里面覆盖了全局的in所以in是一个指针变量,所以并不是15而是4,每次只赋值4个字节,肯定是错了点。代码如下:#include <cstring>#include <cstdio>#include <cstdlib>#define MOD 2000003using namespace std;char s[50], in[15], out[15];in
阅读全文
摘要:该题的思路就是枚举所有的点,当然这么枚举要做到不能够重复和遗漏,所以我们约定值枚举对角线的两个点,最后将最终的结果除以2来计算。由于每次通过枚举对角线的两个点,我们还要计算出另外两个顶点的坐标,所以这里用了一个很牛的公式,直接作加减法就能够出来了,判定下是否为整数。理论上我们马上要到点集中去寻找有没有这两个点,显然这种做法的效率很低,所以这里要用hash表,将顶点的信息的查询优化到接近O(1)。这里把正方形计算另外两个顶点的公式记录如下(已知x1, x2, y1, y2, 求x3, y3, x4, y4): x1 + x2 = x3 + x4; y2 - y1 = x4 - x3; y1...
阅读全文
摘要:不得不说上次看得的这句话是多么对,再差的Hash表都比map好,hash表的查找速度可不是logn能够比的。首先将5个部分拆成2+3,我们选取2的部分进行hash,然后再进行3重for循环。动态申请内存还是比不上静态的啊。代码如下:动态申请内存:#include <cstdio>#include <cstring>#include <cstdlib>#define MOD 20003using namespace std;int rec[105];struct Node{ int x; Node *next;}e[20003];void Hash(int k
阅读全文
摘要:这题直接两个for循环直接TLE,所以这里要先进行一次哈希,然后一次排序,这样只要比较相邻的并且hash值相同的两个串即可。代码如下:#include <cstdlib>#include <cstring>#include <cstdio>#include <algorithm>#define MOD 100000007using namespace std;int N, a[6];struct Node{ int a[6], sum; bool operator < (Node t) const { return sum < t.s
阅读全文
摘要:这题树状数组加离散化TLE,归并排序却过了。代码如下:#include <cstdlib>#include <cstdio>#include <cstring>#include <iostream>#define MAXN 500005using namespace std;int N, a[MAXN], c[MAXN];long long ans;void merge_sort(int l, int r){ if (r > l) { int mid = (l+r) >> 1; merge_sort(l, mid); merge
阅读全文
摘要:直接暴力代码如下:#include <cstring>#include <cstdlib>#include <cstdio>#include <algorithm>#include <map>#include <string>#include <iostream>using namespace std;int N;string ans;map<string, int>mp[15]; map<string, int> :: iterator it;int main(){ int T; ch
阅读全文
摘要:直接暴力。代码如下:#include <cstring>#include <cstdio>#include <cstdlib>#include <map>#include <string>using namespace std;char word[10005][55], c[55];map<string, int>mp;bool Del(int x){ int length = strlen(c), sum = 0; if (length != strlen(word[x])+1) { return false; } fo
阅读全文
摘要:这里参看了大牛的解题思路,学习了很多。原来上下界流的求法是这么的灵活,尤其我是用的临界表存储的边,删除更新很不方便。http://www.shuizilong.com/house/archives/sgu-176-flow-construction/http://hi.baidu.com/lxc_0601/blog/item/39e4e2ecd3be0b2f62d09f95.html这里要进行说明的求解一个有上下界的网络流的步骤:1.首先进行构图,对于那么对流量没有限制的边,我们直接将容量赋值为原始的容量,而对于有流量要求的边,我们将容量减去下界并将其等价与无下界的边。最后就是添加一个附加汇点
阅读全文
摘要:有一条东西向流淌的河,宽为 W,河中有 N 块石头,每块石头的坐标(Xi, Yi)和最大承受人数 Ci 已知。现在有 M 个游客在河的南岸,他们想穿越这条河流,但是每个人每次最远只能跳 D 米,每跳一次耗时 1 秒。问他们能否全部穿越这条河流,如果能,最少需要多长时间。 <= N <= 50, 0 < M <= 50, 0 <= D <= 1000, 0 < W(0<= 1000, 0 < Xi < 1000, 0 < Yi < W, 0 <= Ci <= 1000)。刚看完这题,想当然的认为它是一道最小费用流
阅读全文
摘要:题目意思是有一些蜥蜴在一个迷宫里面,求这些蜥蜴还有多少是无论如何都逃不出来的。题目只给定一个行数,一个最远能够跳跃的距离,列数是不确定的(题目告知列数小于等于20),但是数据一定会是一个矩阵。每只蜥蜴有一个初始的位置,题目保证这些位置都有一些柱子,每次蜥蜴从一个位置跳到另外一个位置的时候,就会由于反作用力使得一根柱子倒下。很显然,这一题,可以用网络流来求解,那么如何去构图呢?首先我们要确定一个贪心思想,即如果从某一根柱子能够直接跳到迷宫的外面,那么我们就将这个点连接到汇点,而不用将这个点连接到其他的点了。对于哪些不能跳出去但是又有柱子的点,那么我们就去按照跳跃距离搜寻有没有其他的柱子能够去..
阅读全文
摘要:该题是给定对个任务,然后告诉你这多个任务在两个不同的核心上执行任务所花费的不同代价,并且还告诉如果其中一些任务不在同一个核心上面运行的话,还有有多余的开销。最后问我们完成所有任务的最小开销是多少? 对于这个问题,我们先把问题简单话一下,如果没有第二个约束条件,仅仅只有在两个核上的运行时间。那么可能你会说对每个时间所花费的时间取一个最小值就可以了,事实也确实如此,但是如果用流网络来建立这个模型的话,那么我们需要将这个事件拆成两个点,从源点流向左边点的容量是一个核心上花费的时间,两个事件点之间的容量为无穷大,右边点流向汇点的容量为该事件在第二个核心上面所花费的时间,由于中间的边的容量是无穷大...
阅读全文
摘要:题义很简单,还记得方格取数(1)的时候,使用状态压缩写的,这里由于行列数太大,因此无法进行压缩。所以要运用的最小割最大流的思想来解这道题。 大概是这样分析的,题义是要我们求在一个方格内取出N个点,使得这N个独立的(不相邻)点集的和最大。我们可以将问题转化为最小割来求解。首先,我们将方格进行黑白相间的染色,然后再将任意一种颜色(黑色)作为源点,一种颜色(白色)作为汇点。我们的算法过程就是一个不断寻找增广路的过程。当我们找到最大流的时,也就是此时不存在从黑色到白色的路径,也即不存在不相邻的两个方格能够连通了。而此时的最大流就是分割两个区间的最小割,拿总合值减去这个最小割就是我们想要得到的结果...
阅读全文
摘要:第一道网络流的应用题,题中要求出至少要多少个围墙才能把狼阻挡在羊群活动的范围外,解决该题的方法就是以狼为源点,羊会汇点,求最小割即为最少的围墙数。出源点和汇点外其余两个网格之间的权值都是1,表示有一头狼能够通过网格走到羊群中去。递归写的sap一直超时,最后还是递归的Dinic过了,无语了。不会非递归伤不起啊。代码如下:#include <cstring>#include <cstdlib>#include <cstring>#include <algorithm>#include <cstdio>#include <queue&
阅读全文
摘要:该题题义是这样的,有N台机器安排去组装电脑,每台电脑有P个零部件,一台可以出产的电脑必须要求每个部件都有。每台机器能够接受的本成品电脑不同,对于每个部件,输入数据给出了0(一定不能够在半成品上出现),1(一定要在上面出现),2(可以出现也可以不出现)。每台机器生产出来的半成品(或者成为了成品)的情况也有不同,对于每个部件0代表经过这个机器加工后,该号不见没有,相反,1代表有。 由于每台机器的处理能力有限,所以这里要将点拆成边,点内的边赋值为产能,其他边均赋值为无穷大。对部件没有要求的机器为源点,对部件都有要求的机器为汇点。考虑好机器与机器之间的传递关系,建图后直接计算最大流,最后在遍历两...
阅读全文
摘要:题中给出了各种点的定义,其实我们只要建立两个虚拟节点就可以了。一个是源点流到所有的p点,一个是汇点,所有的c点流过去,再求最大流就可以了。当然题中的输入数据比较恶心,这里用了字符串的处理方式来解决。 代码如下:#include <cstring>#include <cstdlib>#include <cstdio>#include <algorithm>#include <queue>#define S N#define T (N+1)#define INF 0x3fffffff#define MAXN 105using namesp
阅读全文
摘要:这题和其他的要用二分图匹配不太一样,只要是它允许有重叠的点可以利用,而寻找增广路径的方式是不允许一点重复利用的。所以这题要转换一下方式来间接求得。 首先对于所有的孤立进行搜索,顺带建立边的关系,对于孤立的节点一定要安放一个雷达的。然后对于剩下的的,根据贪心思想,让一个天线直接覆盖两个点的话是最优的策略,于是我们利用二分图匹配这个方法使得所有的匹配成功的边都安装天线。接下来我们再将所有没有覆盖到的点在适当位置安放天线(势必会有重复覆盖的点)。最后将三者的值相加即可。当然第一个结果和第三个结果是可以一起算的。 代码如下:#include <cstdlib>#include <cs
阅读全文
摘要:该题题义为给定网格的中的点的坐标,现在要去将这些点摧毁,有一种武器能够一次摧毁一行或者是一列的所有目标,问最少用多少次该武器能够使得所有的目标消失。这题怎么转化为二分图去做呢,过程是这样的,首先对于每个目标有两种方式能够让其消失,一种是在其所在行上使用武器,一种是在其所在列上使用武器。那么对于所有的目标而言,只要在行列满足之一的地方使用武器就可以全部清除目标。于是我们可以将目标所在行列进行匹配,然后再求最小顶点覆盖就可以了。因为最小顶点覆盖就是满足一条边至少有一个顶点在这个顶点集中。代码如下:#include <cstdlib>#include <cstdio>#inc
阅读全文
摘要:这题一个地方没注意,导致错了很多次,之后还一直没找到错误。出问题的地方就是在第一轮找入度为零的节点的时候直接找的祖先节点,导致祖先节点多次入队~~~代码如下:#include <cstring>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cmath>#include <queue>using namespace std;int N, M, set[10005], pos, cc;int rec[10005][2];char r[10005
阅读全文
摘要:该题在给定了一些大小的关系的基础上询问是否可以断定N个数的大小关系,其实就是一个拓扑排序题。注意题义是在给定M组关系中依次处理,一旦根据1-K(1<=K<=N)能够判定是否确定或者冲突则马上退出来。如果一直到最后一组数据还没有这两种情况的话就是不能确定了。两重for循环建立边的关系,用来完成题目中要求的依次处理,对于每一种情况进行一次拓扑排序,查看是否成环或者确定关系。 成环的判定方式当每次从所有点中选取度为零的节点不能够再进行的时候,此时选取出来的点还没有N个则说明有环的存在; 如果所有的点都能够被取出来并且在整个取的过程中每次都有且尽有1个度为零的节点,那么就说明关系可以确定;
阅读全文
摘要:该题题义是某个人从S点出发,去寻找所有的A,他可以直接到达每个A,也可以通过分身来到达,具体视那种方法所走的路程短而定。换句话说就是可以从A点再走到A点来寻找下一个A,而不选择再从S出发。首先将任意两点之间(A或者S)的距离求出来(通过BFS)然后再建立最小生成树即可。注意输入数据中x,y后面不只一个空格。代码如下:#include <cstring>#include <cstdlib>#include <cstdio>#include <cmath>#include <algorithm>#include <queue>
阅读全文
摘要:最直接的最小生成树,不解释了。代码如下:#include <cstring>#include <cstdlib>#include <cstdio>#include <algorithm>using namespace std;int N, pos, set[105];struct Node{ int x, y, dist; bool operator < (Node t) const { return dist < t.dist; }}e[10005];int find(int x){ return set[x] = x == set
阅读全文
摘要:一道简单的最小生成数,求使得所有的路连通的最小总路程代价中的最长的子路的长度。代码如下:#include <cstring>#include <cstdlib>#include <cstdio>#include <algorithm>using namespace std;int N, pos, set[505];struct Node{ int x, y, dist; bool operator < (Node t) const { return dist < t.dist; }}e[250005];int find(int x){
阅读全文
摘要:计算整个汽车演化过程中所要改变的最少的字符数。改变的字符数的计算方式为1-7位不同位的个数。代码如下:#include <cstdlib>#include <cstring>#include <algorithm>#include <cstdio>using namespace std;int N, pos, set[2005];char s[2005][10];struct Node{ int x, y, diff; bool operator < (Node t) const { return diff < t.diff; }}e
阅读全文
摘要:跟POJ-1860基本一样,bellman求是否存在环。这里吸取了别人的代码,让bellman算法的外循环直接增加一次,再判定是否在这个过程中有无更新推出的情况。代码如下:#include <cstring>#include <cstdlib>#include <cstdio>#include <map>#include <string>using namespace std;int N, pos, cnt;double dis[35];map<string,int>mp;struct Node{ int x, y; do
阅读全文
摘要:计算出是否存在某个源点发出的信息能够到达所有其他点,并且输出满足该情况下的整个路径中最长路径最小的那个源点以及那条最长的边。floyd直接计算,在通过遍历整个二维数组来确定这个最后结果。代码如下:#include <cstdlib>#include <cstdio>#include <cstring>#include <algorithm>#define INF 0x3f3f3f3f#define MAXN 105using namespace std;// 自己到自己的距离要赋值成零int N, G[MAXN][MAXN];void floyd
阅读全文
摘要:该题就是求一只青蛙从1号石头跳到2号石头的所有路径中跳跃距离最大值的最小值。仔细想想的话,将原来dijkstra的dis数组赋值为这个minmax含义,同样满足贪心规则,所以就是普通的dijkstra。代码如下:#include <cstring>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cmath>#define MAXN 205using namespace std;int N;struct Node{ int x, y;}e[MAXN];do
阅读全文
摘要:该题是做最短路专题时的题,但是可惜没有想到如何进行最短路求解。倒是觉得dfs能够得到结果,因为该题对于建立边有严格的条件,递归能够很好的解决这个约束。每次递归时将当前路径的最低等级和最高等级传递下去,然后再进行判断。这里还要注意判定环的存在。后者没有注意的话会MLE。代码如下:#include <cstring>#include <cstdio>#include <cstdlib>#include <algorithm>#include <queue>#define MAXN 105using namespace std;int M,
阅读全文