08 2012 档案

摘要:这是一道面试题,可以说是数据结构中的基础题了,由先序遍历以及中序遍历生成一棵树,然后输出后序遍历。一个递归函数传递5个参数,顶点编号,先序左右区间,中序左右区间,每次进行区间长度判定,当只有一个元素就进行元素判定,递归构树。代码如下:#include <cstdlib>#include <cstdio>#include <cstring>#include <algorithm>#include <iostream>#define MAXN 1005using namespace std;int N, p[MAXN], m[MAXN], 阅读全文
posted @ 2012-08-24 08:31 沐阳 阅读(346) 评论(0) 推荐(0) 编辑
摘要:这题就是求一个矩阵中的最小面积矩阵,使得其和大于一个给定的K,由于是求最优解,所以很自然的想到了二分查找这个值,但是这题我却在不去顶是否满足二分性质的前提下匆忙的选择了二分查找,最终导致了错误。原因在与当一个面积为一个最优解的时候,面积大于该最优解的子矩阵不一定包含这个最优矩阵,例如一个5*5的矩阵的,如果最优矩阵是一个2*2的矩阵,那么1*5的面积为5的矩阵式不会包含这个2*2的矩阵的,所以......代码如下:#include <cstdlib>#include <cstdio>#include <cstring>#include <algorit 阅读全文
posted @ 2012-08-23 18:41 沐阳 阅读(7211) 评论(0) 推荐(0) 编辑
摘要:求一条从一点出发来回的最长路。将问题转化为从某点出发的到达N点的两条不相交的路径。定义dp[i][j]表示第一个点到达i点,第二个点到达j点所经过的最多顶点数,初始状态为dp[1][1] = 1表示从1,1点出发经过的顶点数为1.动态方程:dp[i][j] = max( dp[i][k] + 1 ) 前提是 k,j 之间有边; 整个状态不去更新dp[i][i],因为如果更新了这个状态就可能使得最优解中包含了相同的点。代码如下:#include <cstring>#include <cstdio>#include <cstdlib>#include <m 阅读全文
posted @ 2012-08-22 10:57 沐阳 阅读(217) 评论(0) 推荐(0) 编辑
摘要:听说有了打表算法算法之后,就觉得按位DP太他妈蛋疼了。直接把整个数据规模划分成10000为段的数据进行离线打表。然后再对多余的部分进行暴力就可以了。打表代码:#include <cstdlib>#include <cstring>#include <cstdio>using namespace std;int fun(int x){ if (x == 0) return 0; else return fun(x/10) + x % 10; }bool Ac(int x){ int t = fun(x); if (x % t == 0) return true 阅读全文
posted @ 2012-08-21 21:51 沐阳 阅读(2100) 评论(5) 推荐(1) 编辑
摘要:题意为给定了N棵树,M个蘑菇,一阵风刮来,求期望的幸存的蘑菇的权值。我们可以转化为求每一个蘑菇仔这一阵风过后的期望权值,然后再把所有的蘑菇的权值相加即可。所以我们对于每一棵树进行一次更新,在其安全区域进行更新,这个用线段树来解决,然后再询问一次蘑菇所在地方的安全系数就可以了。代码如下:#include<iostream>#include<cstdio>#include<cstdlib>#include<algorithm>#include<cmath>#include<queue>#include<set>#i 阅读全文
posted @ 2012-08-20 19:16 沐阳 阅读(286) 评论(0) 推荐(0) 编辑
摘要:简单的无向图求割点.代码如下:#include <cstdlib>#include <cstring>#include <cstdio>#include <algorithm>#define MAXN 1005using namespace std;int head[MAXN], idx, LIM, dfn[MAXN], low[MAXN], ti;int subnet[MAXN];bool vis[MAXN];struct Edge{ int v, next; }e[MAXN*MAXN];void AddEdge(int x, int v){ 阅读全文
posted @ 2012-08-20 11:18 沐阳 阅读(228) 评论(0) 推荐(0) 编辑
摘要:不管你是怎么做的,反正我是用二分做的,相当于做了一个预处理。一个最优的序列一定是 1 2 3 .. N .. 3 2 1,或者是 1 2 3 .. N N .. 3 2 1.代码如下:#include <cstdlib>#include <cstdio>using namespace std;long long rec[131100], a, b;void pre(){ rec[1] = 1; long long LIM = 1LL << 32, base = 1; int i; for (i = 2; rec[i-1] <= LIM; ++i) { 阅读全文
posted @ 2012-08-19 22:56 沐阳 阅读(259) 评论(0) 推荐(0) 编辑
摘要:这题如果是要输出所有的解的情况的话,用两个有序表查找可以优化到O(n^3),幸好这题只是要求出一种方案,那么我们就有以下结论:当 N < 8 的时候是无解的当 N > 8 并且 N是一个奇数的话,那么就可以拆成 2 + 5 + 一个偶数,根据哥德巴赫猜想,一个合数一定能够分解成两个素数之和,所以只要遍历一遍素数表即可当 N > 8 并且 N是一个偶数的话,那么就可以拆成 2 + 2 + 一个偶数,同理可以在 O (n / ln(n))的时间内完成。代码如下:#include <cstdlib>#include <cstdio>#include < 阅读全文
posted @ 2012-08-19 22:50 沐阳 阅读(319) 评论(0) 推荐(0) 编辑
摘要:这题就是考察了一个单调队列,做的时候要注意由于首尾相连,所以我们就扩出一倍的空间来简化这个过程。定义f[j]表示在第j号位置结束的连续长度不超过k的最大和,那么f[j] = MAX( sum[j] - sum[k] ),其中就要求满足区间要求,由于每个点都是从前面的sum[k]得来的,所以就可以用一个单调队列来进行同步更新。详见代码:#include <cstdlib>#include <cstring>#include <cstdio>#define INF 0x3fffffff#define MAXN 100005using namespace std; 阅读全文
posted @ 2012-08-18 23:40 沐阳 阅读(628) 评论(0) 推荐(0) 编辑
摘要:这题是给定了一个长度为N的串,问一个固定区域内的最小值和最大值,这题没办法通过DP来求解,因为单纯保留最值的信息是行不通。详见代码:#include <cstdlib>#include <cstdio>#include <cstring>#include <algorithm>#define MAXN 1000005using namespace std;int N, M, seq[MAXN], que[MAXN], front, tail;/* 此题就是要求出给定序列的某一段区间内的最小值和最大值 一个长为N的序列,每次选取M长的区间进行滑动 阅读全文
posted @ 2012-08-18 13:20 沐阳 阅读(221) 评论(0) 推荐(0) 编辑
摘要:这题如果采用普通的DP方程的话果断TLE。所以需要对DP方程进行优化。由于这里龙珠可以随意选取,所以龙珠的编号也就没有了什么意义了,所以直接先对龙珠进行排序,我们只要保证其位置和花费同步排序就可以了。接下来就是优化了,这个部分可以见代码,在上一题中使用的同步滑动指针,这里则不然,需要根据数值来异步滑动指针。代码如下:#include <cstdlib>#include <cstring>#include <cstdio>#include <algorithm>#define INF 0x7f7f7f7fusing namespace std;in 阅读全文
posted @ 2012-08-18 02:06 沐阳 阅读(244) 评论(0) 推荐(0) 编辑
摘要:Description韩父有N个儿子,分别是韩一,韩二…韩N。由于韩家演技功底深厚,加上他们间的密切配合,演出获得了巨大成功,票房甚至高达2000万。舟子是名很有威望的公知,可是他表面上两袖清风实则内心阴暗,看到韩家红红火火,嫉妒心遂起,便发微薄调侃韩二们站成一列时身高参差不齐。由于舟子的影响力,随口一句便会造成韩家的巨大损失,具体亏损是这样计算的,韩一,韩二…韩N站成一排,损失即为C*(韩i与韩i+1的高度差(1<=i<N))之和,搞不好连女儿都赔了.韩父苦苦思索,决定给韩子们内增高(注意韩子们变矮是不科学的只能增高或什么也不做),增高1cm是很容易的,可是增高10cm花费就很大 阅读全文
posted @ 2012-08-17 21:28 沐阳 阅读(774) 评论(0) 推荐(0) 编辑
摘要:通过枚举每个点作为最小值,再通过动态规划求出以每个点作为最小值的左右区间。代码如下:#include <cstring>#include <cstdio>#include <cstdlib>#include <algorithm>#define MAXN 100005using namespace std;typedef long long int Int64;Int64 seq[MAXN], sum[MAXN], ret;int L[MAXN], R[MAXN], N;int main(){ while (scanf("%d" 阅读全文
posted @ 2012-08-17 10:35 沐阳 阅读(299) 评论(0) 推荐(0) 编辑
摘要:这题好像是POJ的一道原题... 首先这题我们能够确定如果一条线段被另外一条线段所包含的话,那么那条包含它的线段的左端点一定小于或者等于这个线段。于是我们按照左端点从小到大排序,左端点相同按照右端点从大到小排序,这样就能够保证所有包含第i条线段的线段一定在前面得到了更新。接着我们就直接要求前面线段的右区间大于改线段,由于用的树状数组,所以用一个数减去这个右端点,所以该右端点就越靠近左边,所以也就能使上树状数组了,需要注意的当两条线段的属性完全一样时,我们要直接把前面的答案赋值给后面的线段,然后再去更新。代码如下:#include <cstring>#include <cstd 阅读全文
posted @ 2012-08-17 01:47 沐阳 阅读(294) 评论(0) 推荐(0) 编辑
摘要:这题一开始想用状态压缩DP解,后来发现状态开不下...还是没有很好的理解啊。这里将棋盘看做是两个正方形,由于只能够走对角线,所以两个正方形可以看做是无关的,因此我们只要求出每个正方形走相应步数的方案。对于k不而言,在两个正方形里面就有(1, k-1), (2, k-2)...例如这样的分法,必须保证所有的分法都是合法的。现在问题就在于如何去求一个N*N的矩阵能放置一些棋子,这些棋子要求上下左右不能够在同行同列的方案数。其实就是一个简单的递推而已,我们定义dp[i][j]表示到第i行放置j个方案数,那么dp[i][j] = dp[i-1][j] + dp[i-1][j-1]*(n-j+1),其实 阅读全文
posted @ 2012-08-17 01:39 沐阳 阅读(301) 评论(0) 推荐(0) 编辑
摘要:首先说明这题不是在线算法,也不能说是离线算法,就是一个预处理能够把所有的结果全部算出来再O(1)的时间得到答案。首先我们要将一这种上下属的关系通过一个dfs转化为一维的关系,相同属性(指为同一个人的下属)的话,那么在物理上就是连续的。这样处理后,我们考虑一个员工能够被替代的话,那么替代他的人的能力值就一定是比他高的,因此我们按照能力值对所有的人进行一次排序,能力值相同的就按照标号从小到大排,这样的话,就能够保证每次询问一个点时,线段树中的所有值都是满足上下属关系的。排好序后,再从左到右扫描一遍,每次先查询如果解雇这个员工,谁将成为他的最佳替代者。代码如下:#include <cstdli 阅读全文
posted @ 2012-08-15 22:31 沐阳 阅读(729) 评论(0) 推荐(0) 编辑
摘要:首先将没有特殊点的所有的情况都计算出来,再将给定的点都计算到左上角的标记点,最后查看有多少个点已经被覆盖了,减去该部分,最后用快速幂输出结果,注意这里要用long long。代码如下:#include<iostream>#include<cstdio>#include<cstdlib>#include<algorithm>#include<cmath>#include<queue>#include<set>#include<map>#include<cstring>#include< 阅读全文
posted @ 2012-08-15 16:54 沐阳 阅读(271) 评论(0) 推荐(0) 编辑
摘要:简单矩阵...代码如下:#include <cstring>#include <cstdio>#include <cstdlib>#include <iostream>using namespace std;unsigned int temp[5][5] = { {0, 0, 0, 0, 0}, {0, 2, 3, 1, 1}, {0, 1, 2, 3, 1}, {0, 1, 1, 2, 3}, {0, 3, 1, 1, 2}};unsigned int fix(unsigned int x){ if (x > 0xff) { x ^= 0 阅读全文
posted @ 2012-08-15 11:21 沐阳 阅读(255) 评论(0) 推荐(0) 编辑
摘要:记录每个节点从四个方向来的最优值,用了那个spfa后,因为要标记入队,所以就会牵涉到一个节点的自环现象,所以这里就直接在队列里面记录其当前距离,不进行队列优化,也过了。该题的边竟然是双向的。代码如下:#include <cstring>#include <cstdlib>#include <cstdio>#include <algorithm>#include <queue>using namespace std;typedef long long int Int64;int N, M, idx, mp[255], head[1500 阅读全文
posted @ 2012-08-15 10:05 沐阳 阅读(358) 评论(0) 推荐(0) 编辑
摘要:这题虽然说是什么按位DP,其实尼玛不是组合数学么。不过硬是用模板的按位DP实现了,其实也就是记忆化搜索,本题恶心就在于有负数的存在,其实对付它就是把正数的第33位都变成1,用long long来处理,这样既保证了负数小于正数,又可以化成单一的区间了。在按位统计的时候记得当1出现在33位的时候不统计这个1。这题思路也就是先把[a, b]区间内含有一个1,两个1,三个1...的数的个数全部统计出来,一个for循环就能够找出该数字出现在有几个1的一段上,然后再二分查找答案,最后输出。代码如下:#include <cstdlib>#include <cstring>#inclu 阅读全文
posted @ 2012-08-14 10:32 沐阳 阅读(689) 评论(0) 推荐(0) 编辑
摘要:这题只需要预处理两个数组就可以了,那就是一个保留从1到N,这个N个数字连在一起的长度,以及另外一个数组表示重复打印112123...123..N的这样一个打印到N的串的长度。接下来进行两次二分查找便可得到答案了。代码如下:#include <cstring>#include <cstdlib>#include <cstdio>#define MAXN 32000using namespace std;typedef long long int Int64;Int64 N, c[MAXN+5], s[MAXN+5];inline int Len(int x){ 阅读全文
posted @ 2012-08-13 19:11 沐阳 阅读(361) 评论(0) 推荐(0) 编辑
摘要:前面用组合数学来写这题实在是被边界条件搞得头昏脑胀,这里就直接按位DP,每次dfs传递0和1的个数这两个参数下去即可。代码如下:#include <cstdlib>#include <cstdio>#include <cstring>using namespace std;int a, b, bit[35], dp[35][35][35];int dfs(int pos, int zero, int one, int limit){ if (pos == -1) { return zero >= one; } if (!limit && 阅读全文
posted @ 2012-08-13 16:43 沐阳 阅读(364) 评论(0) 推荐(0) 编辑
摘要:http://acm.timus.ru/problem.aspx?space=1&num=1057其实这题可以算是一个组合数的题目了,主要是将基于其他进制转化为基于2进制的算法,对于某一位不为1的话,那么取其他位的话是一定不满足题意的,所以要找到一个数的最高位大于1,将这一位以及后面的每一位都赋值为1,然后就是一个按位DP的过程了,dp[len][statu]表示长度剩余量为len,要求1的个数为statu个时,并且对后面的位没有要求的情况下,所有可能的解。代码如下:#include <cstring>#include <cstdio>#include < 阅读全文
posted @ 2012-08-13 16:01 沐阳 阅读(286) 评论(0) 推荐(0) 编辑
摘要:这题的状态真的是很难想到,网上的代码都惊人的相似...另一种解法,相比而言好接受一点:#include <cstring>#include <cstdio>#include <cstdlib>#include <algorithm>using namespace std;typedef unsigned long long Int64;Int64 dp[20][3], N;int digit[20];Int64 dfs(int pos, int statu, int limit){ if (pos == -1) { // 如果到了已经枚举了最后一 阅读全文
posted @ 2012-08-13 01:31 沐阳 阅读(474) 评论(2) 推荐(0) 编辑
摘要:这题要注意的就是要构造出两个端点出来,然后直接开辟状态dp[i][j]表示i,j之间的囚犯都救出的最少的金币数,注意此时的边界i,j是不取的。初始条件是dp[i][i+1] = 0.代码如下:#include <cstring>#include <cstdlib>#include <cstdio>#include<iostream>using namespace std;const int inf = 0x3fffffff;int N, P, loc[105], dp[105][105];int dfs(int a, int b){ if(b - 阅读全文
posted @ 2012-08-12 23:23 沐阳 阅读(373) 评论(0) 推荐(0) 编辑
摘要:这题一开始便想着DP求解,但是细想一下是不对的,因为这种位操作在没有到最后一次计算时是无法得到最优解的,也即不存在最优子结构。首先当 a 与 b 做运算时,我们分析64位上的每一位,我们知道 & 和 ^ 操作总是有一个可以产生0的,那么对于两个64的数而言我们总可以至少使得其32位等于0,再将这个数x与c做运算的话,我们就直接把x & c,那些已经为0的位一定会还是0,其余的位不是0就是1,如果结果中 1比0多,那么我们对c取反,反正就是至少会有一半变成0,以此下去超过6个数,那么这个数就一定就是0了。对于小于0的情况,我们就直接暴力。代码如下:#include <cst 阅读全文
posted @ 2012-08-12 21:30 沐阳 阅读(325) 评论(0) 推荐(0) 编辑
摘要:比赛的时候竟然没有想到这题可以用树状数组过,由于数字的区间比较小,所以直接开设一个树状数组,定义sum(i) 表示小于i的数的总数。那么判定一个数是否有的条件就是计算sum(i+1) == sum(i) 便可以了,查找第K大的数,也就可以直接二分了。代码如下:#include <cstdlib>#include <cstring>#include <cstdio>#include <algorithm>#define MAXN 100000using namespace std;int c[MAXN+5];int lowbit(int x){ r 阅读全文
posted @ 2012-08-12 20:28 沐阳 阅读(300) 评论(0) 推荐(0) 编辑
摘要:这题可以用二分枚举答案来求解,每次枚举一个答案时我们总是选取满足要求的每个零件的价格最小者,如果金钱能够满足的话就枚举一个更大的质量,这里最好将质量离散化,这样就能枚举每个点都用相应的品质对应。代码如下:#include <cstring>#include <cstdio>#include <cstdlib>#include <algorithm>#include <map>using namespace std;map<int,int>mp;int fee[1005];struct Node{ char name[25] 阅读全文
posted @ 2012-08-12 20:06 沐阳 阅读(382) 评论(0) 推荐(0) 编辑
摘要:该题题意是要求给定a,b区间内有多少个数满足二进制表示法内0的数目多余1的数目。详见代码:#include <cstdlib>#include <cstdio>#include <cstring>#include <algorithm>using namespace std;int c[40][40];void pre(){ c[0][0] = 1; for (int i = 1; i <= 30; ++i) { c[0][i] = 1; for (int j = 1; j <= 30; ++j) { c[j][i] = c[j][. 阅读全文
posted @ 2012-08-12 10:05 沐阳 阅读(230) 评论(0) 推荐(0) 编辑
摘要:这题是要求一段区间内的不重复的数字之和。我们通过对询问区间的右端点进行排序,然后记录每一数字的上一次的出现的位置,由于询问都是不回溯的那么就可以线性的更新了。代码如下:#include <cstdlib>#include <cstdio>#include <cstring>#include <algorithm>#define MAXN 50005using namespace std;typedef long long int Int64;int N, M, seq[MAXN], last[1000005];Int64 ans[200005], 阅读全文
posted @ 2012-08-11 11:13 沐阳 阅读(316) 评论(1) 推荐(0) 编辑
摘要:这题是定义如下的一个数:S(0, 0) = 1; S(n, 0) = 0 for n > 0;S(0, m) = 0 for m > 0;S(n, m) = m S(n - 1, m) + S(n - 1, m - 1), for n, m > 0.也就是题中所说的把一个含有n个元素的集合分成m份,共有多少种分法。现在题目就是要求S(n, m)的奇偶性。如果m是一个偶数的话,那么我们可以推出 S(n, m)Ξ S(n-1, m-1) (mod 2),如果m是一个奇数的话,我们推出S(n, m)Ξ (S(n-1, m) + S(n-1, m-1)) (mod 2)。后面看到某一 阅读全文
posted @ 2012-08-10 23:03 沐阳 阅读(607) 评论(0) 推荐(0) 编辑
摘要:详见代码:方法一:#include <cstdlib>#include <cstring>#include <cstdio>using namespace std;char s[1005];int len, Mp[25] = {1,1,2,6,4,2,2,4,2,8,4,4,8,4,6,8,8,6,8,2};// 直接计算出其循环节为20这里将0-19的列表于上,当N<5时直接输出,其余需要递归N/5因为这个表是删除了所有的5的倍数的 int slove(){ int ans = 1; while (len) { len -= !s[len-1]; a 阅读全文
posted @ 2012-08-10 11:24 沐阳 阅读(1450) 评论(0) 推荐(0) 编辑
摘要:这题打表找下规律就可以了,定义一个变量来表示增量,那么这个变量的格律就是 add = (add± 1) * 2手写了大数的类,幸好只有-1这个值,这个类是没定义减法运算的。代码如下:#include <cstdlib>#include <cstdio>#include <cstring>#include <cmath>#include <algorithm>using namespace std;typedef long long int Int64;Int64 rec[65];int N;struct BigInteger 阅读全文
posted @ 2012-08-09 20:34 沐阳 阅读(448) 评论(0) 推荐(0) 编辑
摘要:这个是参考了别人之后的代码,POJ上0MS过了。Orz......对于一个序列在提取了2,5之后,例如1,2,3,4,5,6,7,8,9,10,我们可以将其中的奇数和偶数分开来对待,对于偶数序列2,4,6,8,10由于原序列会被提取出2,所以就退化成了1,2,3,4,5,这个奇数序列,对于奇数序列1,3,5,7,9我们就可以来统计3,5,7的数量了,同样出现的次数是总长度N=10除以10(单位出现区间)再判定N%10是否大于要求得数,对于这个奇数序列由于5是要被提取的,所以又变成了1这个序列,更多数可能更好看了。如此递归下去便行了。代码如下:#include <cstdlib>#i 阅读全文
posted @ 2012-08-09 11:08 沐阳 阅读(704) 评论(0) 推荐(0) 编辑
摘要:这题写的真心有点纠结。首先确定需要多少位来容纳这个数,然后找到第一个要更新的位置,再逐位更新。代码如下:#include <cstdlib>#include <cstdio>#include <cstring>#include <algorithm>#include <cmath>using namespace std;typedef long long int Int64;bool hash[20];int digit[10], Most;Int64 s[10], f[20], N;void pre(){ f[0] = s[0] = 阅读全文
posted @ 2012-08-08 22:23 沐阳 阅读(469) 评论(0) 推荐(0) 编辑
摘要:Description某校数据结构课程设计期末考核即将来临。为了考查学生对树结构的认识,同时也检验学生的编程能力,该校将考核的一项内容定为:要求编写程序按编号顺序打印出节点个数不少于m的所有二叉树。编号规则:·仅有一个节点的树编号为1。·当满足以下条件之一时,定义二叉树a的编号比b大:1.a的节点数比b多。2.若a的节点数与b相等,且a的左子树编号比b的左子树大。3.a的节点数和左子树编号都和b相等,且a的右子树编号比b的右子树大。二叉树的节点用大写X表示,例如:当然当m较大时,检验答案对错的工作也是很繁重的,所以教师只打算对其中的若干个编号的二叉树进行抽查,请编制一个程序 阅读全文
posted @ 2012-08-08 15:08 沐阳 阅读(437) 评论(0) 推荐(0) 编辑
摘要:卡特兰数 转自http://blog.163.com/lz_666888/blog/static/1147857262009914112922803/ Catalan数 中文:卡特兰数 原理: 令h(1)=1,h(0)=1,catalan数满足递归式: h(n)= h(1)*h(n-1) + h(2)*h(n-2) + ... + h(n-1)h(1) (其中n>=2) 另类递归式: h(n)=((4*n-2)/(n+1))*h(n-1); 该递推关系的解为: h(n+1)=C(2n,n)/(n+1) (n=1,2,3,...) 我并不关心其解是怎么求出来的,我只想知道怎么... 阅读全文
posted @ 2012-08-08 09:06 沐阳 阅读(298) 评论(0) 推荐(0) 编辑
摘要:先二分找到这个非平方数,然后对一个一个区间进行求和的预处理。要注意边界问题。代码如下:#include <cstdlib>#include <cstdio>#include <cmath>#include <algorithm>using namespace std;typedef long long Int;Int N, num;long long int sum[1000005];Int bsearch(Int l, Int r) { Int mid, left; while (l <= r) { mid = (l + r) >& 阅读全文
posted @ 2012-08-07 20:30 沐阳 阅读(208) 评论(0) 推荐(0) 编辑
摘要:这里有多个点与原点的连线共线的话,那么需要对其进行并组,将前一个作为单独的一个,把前两个作为单独的一个...最后直接分组背包就可以了。代码如下:#include <cstdlib>#include <cstdio>#include <cstring>#include <algorithm>#define MAXN 205using namespace std;int N, M, cnt[MAXN], vis[MAXN], idx;int f[40005];struct Node{ int x, y, t, v; bool operator < 阅读全文
posted @ 2012-08-07 20:27 沐阳 阅读(238) 评论(0) 推荐(0) 编辑
摘要:这题虽说解题报告中说的是简单题,但比赛中AC率以及提交量并不是很高,主要是数据范围太大,有点吓人,而且含有trick。题目给定b,p,M 问 0 <= n <= M 中有多少个数满足 n^(n!) ≡ b (MOD p),并且可恶的是这里没有提到任何数的特殊性质,给定都只是限定在正整数且p>0。有欧拉定理我们知道 n^(phi(p))≡ 1 (mod p) 但是这里要求gcd(n, p) = 1,显然题目并没有这么要的数据,那么如果题目给定是满足n,p互质的话,那么我们就可以知道n^(x) mod p 是有循环节的,这个循环节就是n^(phi(p)),如果n,p不互质的话,那 阅读全文
posted @ 2012-08-07 10:46 沐阳 阅读(892) 评论(1) 推荐(0) 编辑
摘要:转自http://www.cnblogs.com/suno/archive/2008/02/04/1064368.html利用积性函数的优化.这个文章主要介绍了3算法1线性时间筛素数2线性时间求前n个数的欧拉函数值3线性时间求前n个数的约数个数一、首先介绍下积性函数。下面是wiki的条目:在非数论的领域,积性函数指有对于任何a,b都有性质f(ab)=f(a)f(b)的函数。在数论中的积性函数。对于正整数n的一个算术函数f(n),当中f(1)=1且当a,b互质,f(ab)=f(a)f(b),在数论上就称它为积性函数。若某算术函数f(n)符合f(1)=1,且就算a,b不互质,f(ab)=f(a)f 阅读全文
posted @ 2012-08-06 18:47 沐阳 阅读(1061) 评论(0) 推荐(0) 编辑
摘要:线性筛选法之所以称之为线性就是因为其对于每一个合数只用其最小的素因子将其筛选出来。代码如下:#include <cstdlib>#include <cstdio>#include <algorithm>#define MAXN 1000000using namespace std;int p[1000005], pri[1000005], idx = -1;void GetPrime(){ for (int i = 2; i <= MAXN; ++i) { if (!p[i]) { // 说明i是一个素数 pri[++idx] = i; ... 阅读全文
posted @ 2012-08-06 17:27 沐阳 阅读(621) 评论(0) 推荐(0) 编辑
摘要:本文转自http://blog.sina.com.cn/s/blog_694034130100wlrh.html(修改了少量有误的地方)欧拉函数:对于一个正整数n,小于n且和n互质的正整数的个数,记做:φ(n),其中φ(1)被定义为1,但是并没有任何实质的意义。特殊性质:当n为奇数时,φ(2n)=φ(n)。完全余数集合:定义小于n且和n互质的数构成的集合为Zn,称呼这个集合为n的完全余数集合。显然,对于素数p,φ(p)= p - 1.对于两个素数p、q,他们的乘积n = pq 满足φ(n) =(p-1)(q-1)证明:对于质数p,q,满足φ(n) =(p-1)(q-1)考虑n的完全余数集Zn 阅读全文
posted @ 2012-08-06 14:33 沐阳 阅读(1141) 评论(0) 推荐(1) 编辑
摘要:阶乘末尾0的个数有一个题目说的是求 100 的阶乘末尾有多少个 0. 题解中给出的讲解提到, 一个数 n 的阶乘末尾有多少个 0思路:一个数 n 的阶乘末尾有多少个 0 取决于从 1 到 n 的各个数的因子中 2 和 5 的个数, 而 2 的个数是远远多余 5 的个数的, 因此求出 5 的个数即可. 题解中给出的求解因子 5 的个数的方法是用 n 不断除以 5, 直到结果为 0, 然后把中间得到的结果累加. 例如, 100/5 = 20, 20/5 = 4, 4/5 = 0, 则 1 到 100 中因子 5 的个数为 (20 + 4 + 0) = 24 个, 即 100 的阶乘末尾有 24 个 阅读全文
posted @ 2012-08-06 08:34 沐阳 阅读(2223) 评论(0) 推荐(1) 编辑
摘要: 阅读全文
posted @ 2012-08-06 08:15 沐阳 阅读(256) 评论(0) 推荐(0) 编辑
摘要:首先这题可以用期望DP来计算最后的期望值,由于这题每张卡片对应的概率是不相同的,所以不能像POJ-2096那样dp[i]表示拿到了i 张卡片来表示状态,而是要开一个 1<<N的状态来压缩状态表示拿到不用的卡片的期望值。对于给定的N,我们有dp[(1<<N)-1]=0,因为这已经是最后的状态了。对于dp[i] 我们需要分析其能够到达的状态,如果 N=6, i 的二进制位为 011011,那么可能买零食不改变原来状态,也就是中了已经有了的卡片或者是没有中卡片,所以到达原来状态的概率是p[1]+p[2]+p[4]+p[5]+NONE,这一项是要移到待会儿方程的左边去解的,因为 阅读全文
posted @ 2012-08-04 22:19 沐阳 阅读(1215) 评论(0) 推荐(1) 编辑
摘要:这题主要是要将两个串的比较进行优化,不能够每次都从起始位置进行匹配。这里用到了线段树进行优化,将每段区间的hash值进行更新和维护,通过找某一点的有连续段最长相同串即可。代码如下:#include <cstdlib>#include <cstring>#include <cstdio>#include <algorithm>#define MOD 100000003#define T 29LLusing namespace std;typedef unsigned int Int64;// 这里建立棵线段树记录某一短区间的hash值 char s 阅读全文
posted @ 2012-08-04 22:17 沐阳 阅读(368) 评论(0) 推荐(0) 编辑
摘要:这题是按照解题报告上的思想来写的。觉得这个想法确实是很麻烦。现大概说下思路:首先我们需要通过dp求出每一个点上下左右的延伸距离,这个距离就是连续的1的个数。预处理好这个信息后。我们不是去枚举每个点,而是去枚举每条对角线上的点,按照上面的说法,一条很明显的规则:所有边由1组成的正方形的对角线一定是矩形的对角线,相比N^2的枚举每个点,这个做法有个好处就是减少重复计算。我们的主要思想还是确定一个点为目标正方形的左上角点,然后取右、下的较小值作为其可及域,我们只需要统计这个区域内的点是否能够能够反向覆盖。对于对角线 L, 我们从左上角到右下角进行遍历, 设当前点的坐标为(i, j),对角线坐标是1( 阅读全文
posted @ 2012-08-03 14:21 沐阳 阅读(361) 评论(0) 推荐(0) 编辑
摘要:这题就是一个数据量大点的a+b+c+d+e = 0的判定,可以用哈希表来做,也可以用来个有序表来寻找解。时间复杂度前者接近O(n^3),后者则为O(N^3).代码如下:哈希表:#include<iostream>#include<map>#define MOD 1000003LLusing namespace std;typedef long long LL;const int N = 205;LL a[6][N];int head[1000005], idx;struct Node{ LL v; int next; }e[40005];void add(LL key) 阅读全文
posted @ 2012-08-02 21:07 沐阳 阅读(379) 评论(0) 推荐(0) 编辑
摘要:直接维护好两个数组就可以了,每次访问得到区间的最小值和最大值。代码如下:#include <cstdlib>#include <cstdio>#include <cstring>#include <algorithm>#include <cmath>using namespace std;int N, M, seq[50005], Min[50005][20], Max[50005][20];void Minbuild(){ int LIM = (int)log2(double(N)); for (int i = 1; i <= 阅读全文
posted @ 2012-08-01 22:26 沐阳 阅读(209) 评论(0) 推荐(0) 编辑
摘要:该题时间跨度太大,如果直接把时间建树的话显然内存不足,那么我们考虑到只有10^5朵花,于是要采取离散化,但是如果只是离散化花朵的时间的话,那么当我们去查询某个时间的时候,这个时间点在线段树里面的信息的不存在的,于是也就得不到正确的答案,因此我们要离散化花朵和询问的所有时间,这样信息就完备了。代码如下:#include <cstdlib>#include <cstdio>#include <cstring>#include <algorithm>#include <map>using namespace std;int N, M, ti 阅读全文
posted @ 2012-08-01 10:48 沐阳 阅读(233) 评论(0) 推荐(0) 编辑
摘要:对于这样一道有着如此强烈限制条件的题目(任意两个点一定有边,而且是单向边),表示拥有各种解法,甚至连随机化的方法的AC率都不会太低。这里考虑到不会存在二个点成环的情况,那么我们要论证的就是三个以上的点成环那么就一定有三个点能够成环。对于N个点成环的情况,我们可以选取连续的三个点,如果两边的两个点的边的方向刚好使得三个点成环的话,那么就说明我们的假设成立,如果不是的话,那么就变成了N-1个点成环,以此类推,就一定能够找到3个构成的一个环。代码如下:#include <cstdlib>#include <cstring>#include <cstdio>#inc 阅读全文
posted @ 2012-08-01 10:08 沐阳 阅读(835) 评论(0) 推荐(0) 编辑
摘要:这题比赛的时候纠结了不少...对于A进制的一个数,先将其左移N位使得其成为一个整数,然后再将这个整数化为B进制的一个数,然后我们只需要考虑这个数是否能够整除A^N即可(因为我们前面左移了N位),我可以将B进制的这个数先进行左移无限位,那么当有A^N 整除 B^INF 时我们就可以将这个除尽,然后我们再将B右移INF位便可以了。这里就把问题转化为了A^N能够整除B^INF进制了,进一步我们可以得到B包含所有A的质因子便为判定条件了。代码如下:#include <cstdlib>#include <cstdio>#include <cstring>#includ 阅读全文
posted @ 2012-08-01 09:50 沐阳 阅读(531) 评论(0) 推荐(0) 编辑
摘要:最后才明白题目的意思可以直接抽象为对于每一位,所有数字的0个数乘以1的个数,再将每一位的数恢复过来。自己的做法也是枚举每一个二进制位,对于已经求了 ai,ai+1...aN-1,aN个数的二进制位之后再用ai-1的这一位的情况来判定这一位会增加多少个1。代码如下:#include <cstring>#include <cstdio>#include <cstdlib>#include <algorithm>using namespace std;typedef long long int Int64;// 1000000 这个数字只有最多19位i 阅读全文
posted @ 2012-08-01 09:25 沐阳 阅读(260) 评论(0) 推荐(0) 编辑
摘要:这题不要去考虑每一个时刻的情况,而要考虑每一个位在所有时间上的叠加效果。对于长度为Lf的母串和长度为Ls的子串来说,每个字符匹配的长度都是Lf-Ls+1位。代码如下:#include <cstring>#include <cstdio>#include <cstdlib>using namespace std;char f[2000005], s[2000005];int lens, lenf, cnt[30];int main(){ int T, LIM; long long int ans; scanf("%d", &T); 阅读全文
posted @ 2012-08-01 09:21 沐阳 阅读(199) 评论(0) 推荐(0) 编辑
摘要:将所有括号都找出来,枚举所有的可能,再用strcmp排下序就可以了。标程用到的方法更好,直接标记每个括号属于哪一个括号组,然后直接解压状态即可。代码如下:#include <cstdlib>#include <cstring>#include <cstdio>#include <algorithm>using namespace std;char s[210], rec[1050][210];int stack[15], top, length, cnt;struct Parentheses{ int l, r;}P[15];void init( 阅读全文
posted @ 2012-08-01 09:18 沐阳 阅读(265) 评论(0) 推荐(0) 编辑
摘要:要求输出每个单词在不产生歧义的情况下的最短前缀,直接构造出一颗字典树就可以了。先执行插入操作,对每一个单词经过的路径都进行一个自增的操作。再一次搜索每一个单词,当其遇到覆盖次数为一,或者是到了单词末尾就输出。代码如下:#include <cstdlib>#include <cstdio>#include <cstring>#include <algorithm>using namespace std;int N, idx;char s[1005][25], rec[25];struct Node{ int cnt, ch[26];}e[30000 阅读全文
posted @ 2012-08-01 09:16 沐阳 阅读(311) 评论(0) 推荐(0) 编辑
摘要:这题用匈牙利算法是无论如何也过不了的,边太多了。利用简单的贪心规则,我们每次选取最优的匹配方案来进行匹配,在划分上我们采用工资要求为负值的去寻找工资要求为正值的人。对于一个要求工资比他低的男人来说,其实就是优先最有钱的男人,因为能与之匹配的女生是最多的,在选取女生的时候,就选择满足要求下工资最高的女生,因为这种女生最难满足要求,这一对配对对后面的匹配来说是最优的。女生同理。代码如下:#include <cstring>#include <cstdio>#include <cstdlib>#include <algorithm>#define MA 阅读全文
posted @ 2012-08-01 09:13 沐阳 阅读(261) 评论(0) 推荐(0) 编辑
摘要:该题就是简单的二维树状数组,保留一份棋盘的最新状态即可,树状数组里面就只保留在原有基础上增加或者减少的某一种饺子的数量。代码如下:#include <cstring>#include <cstdlib>#include <cstdio>using namespace std;char op[5];char G[1050][1050];int cc[1050][1050];// 数组中存储韭菜饺的数量,白菜饺的数量通过总数量减去韭菜饺来求void init(){ int k = 0; // 定义韭菜为1,白菜为0 for (int i = 1; i <= 阅读全文
posted @ 2012-08-01 09:08 沐阳 阅读(226) 评论(0) 推荐(0) 编辑
摘要:由于只有最多16种组合情况,所以就直接暴力枚举求解。这里题目有个要求就是按照字典序相对较小的输出规则输出,那么我们可以想到在兴趣数相同的情况下要不要去更新最优值,这就牵涉到我们刚开始的时候求解出来的解是否一定是字典序最小的,或则最后求解出来的解就是字典序最小的,我是采用压缩后的二进制数的最高位代表最小的兴趣,所以从最高位通过自减操作能够保证每次得到的该兴趣数的第一个解都是字典序最小的。#include <cstdlib>#include <cstring>#include <cstdio>#include <algorithm>using nam 阅读全文
posted @ 2012-08-01 09:02 沐阳 阅读(325) 评论(0) 推荐(0) 编辑
摘要:一个网格中的图形,如果其面积只取方格的整数倍的时候,那么我们有如下公式。设面积为Area,多边形内部的整点个数为OnEdge,多边形轮廓线上的整点个数为InSide,那么有公式 Area = OnEdge / 2 + InSide - 1代码如下:#include <cstdlib>#include <cstdio>#include <cstring>using namespace std;int main(){ int T, N; long long int ret, S; scanf("%d", &T); while (T-- 阅读全文
posted @ 2012-08-01 09:00 沐阳 阅读(267) 评论(0) 推荐(0) 编辑

点击右上角即可分享
微信分享提示