09 2012 档案
摘要:求树上的每个节点能到达的最远距离。 先预处理出每个节点从叶子上来的最大距离和次大距离,并且记录最大距离是从哪个儿子上来的。 对于每个节点,它能到的最大距离,要不就是走到自己的某个叶子,要不就是走到某个祖先节点然后转弯进入这个祖先的另一个儿子。向下DP,传递不经过这棵子树到该顶点的最大距离。 1 #include <string.h> 2 #include <stdio.h> 3 #include <algorithm> 4 #define MAXN 10001 5 #define INF 0x3f3f3f3f 6 using namespace std; 7
阅读全文
摘要:水题。。记录每个节点的孩子个数就可以了。。 1 #include <string.h> 2 #include <stdio.h> 3 #include <vector> 4 #include <algorithm> 5 #define MAXN 16001 6 #define INF 0x3f3f3f3f 7 using namespace std; 8 9 struct egde{10 int v, n;11 }e[MAXN*2];12 int n, tu, tv, ans;13 int first[MAXN], es;14 vector<
阅读全文
摘要:一个序列长度为n的序列P(1,n),构造一个序列Q,长度为N并且由1~N组成。一开始Qn对在P1的位置,接下来每秒Q都会整体右移一个位置,直到2N秒后和P没有交集。Ai代表第i秒P和Q交集元素的个数,Bi代表位置重合并且元素相等的元素个数。令Ci=max(Ai-Bi),构造一个序列,使Ci最小。 Ci最小是N-sqrt(N),官方题解说的比较详细。构造序列这个地方看了半天才看明白他是怎么构造的,对于S序列,可以这么理解:给出一个序列x[1,n],以及S(a1,a2,a3....),对应的操作就是先把x[1~a1]翻转,再把[a1+1,a1+a2+1]翻转....,比如x[]=(1,2,3...
阅读全文
摘要:经典页面调度问题,理想算法就是移出从现在开始最久未使用的。 线段树中存正在使用的页面(题中是模版。。)下次出现的时间,每次选出现时间最晚的扔掉。如果遇到一个已经在内存中的页面,也要跟新该页面在线段树中的值。 1 #include <stdio.h> 2 #include <string.h> 3 #include <algorithm> 4 #define lson l,m,p<<1 5 #define rson m+1,r,p<<1|1 6 #define calm l+r>>1 7 #define MAXN 10000
阅读全文
摘要:求至少经过K条边,到达终点的最短路(K<=50)。 K比较小,先用Bellman求出走50步到达每个点的最短路,然后把50步的可达点加到队列里SPFA即可。 题解是直接二维最短路的,不过好像比bellman+spfa慢。。目前排在HDOJ第一。。 1 #include <string.h> 2 #include <stdio.h> 3 #include <queue> 4 #define MAXN 5005 5 #define MAXE 200005 6 #define INF 0x3f3f3f3f 7 struct edge{ 8 int u,v,n
阅读全文
摘要:用若干个-1到2的数组成一个最接近D的数(-1<D<2)。过程中不能超过2。 吐槽一下题目,看了半天才看明白。。。。排个序然后背包。。 1 #include <stdio.h> 2 #include <string.h> 3 #include <algorithm> 4 #define MAXN 205 5 int cas,n,tot,x[MAXN],d[240005]; 6 double x1; 7 int main(){ 8 //freopen("test.in","r",stdin); 9 scanf
阅读全文
摘要:求最小的尾数为X的平方数。 符合情况的数不会有太多,从后向前搜就可以了。 1 #include <string.h> 2 #include <stdio.h> 3 #include <algorithm> 4 #define INF 0x3fffffff 5 typedef long long LL; 6 int cas,n,num[15],len,ans; 7 LL sqr(int x){ 8 return (LL)x*x; 9 }10 void dfs(int l,int mul,int pre){11 if(l==len){12 ans=st...
阅读全文
摘要:题解写了N多方法,我用的是最水的那种。。 起始区间只有(0 <= Fi <= 500),500秒之后排名必然不会变化了。。所以,暴力500秒,然后排个序就行了。 1 #include <stdio.h> 2 #include <string.h> 3 #include <algorithm> 4 #define MAXN 50010 5 struct stt{ 6 int s,t,v,id; 7 bool operator <(const stt& st)const{ 8 return t>st.t||(t==st.t&
阅读全文
摘要:求比N小的因数最多的数,因数相同时取较小的的。(N<=10^80) 没想法的题目,没想到是搜索。。 首先因子数目 f[i] = ∏(p[i]+1) ,p[i]是所有质因数的个数,这个应该都知道。如果要使因子最多并且数最小,不会用到太大的质数,这个我也不知道怎么证明。。原题解也没有证明。。。 用一个四元组[K,F,N,A[]]表示数K有F个因数,包含N个质因数,每个质因数P[i]分别有A[i]个。然后搜索就可以了,添加一个已有质数A[i],四元组转化为[K*P[i],F/(A[i]+1)*(A[i]+2),N,A[i]+1],添加一个新的质数A[i],四元组转化为,[K*P[i],F*..
阅读全文
摘要:给出一个区间以及两种区间操作,[1 l,r,c]把l~r的点染成c色,[2,l,r,c]查询l~r内颜色为c的点的数目。 因为c的数目太大,用线段树是存不下的,所以只能另辟蹊径了。虽然网上有线段树的方法,但那个Max-Min剪枝完全是没有作用的,随便出一组数据,把所有点间隔染成3,5,然后查4,这样用线段树不知道要跑多久。。。 题解说这题是裸的分块HASH。。还没写过,学习了。其实就是将原区间划分乘sqrt(n)个区间,每次暴力查询和跟新两边的区间,中间的区间直接用hash存每种颜色的节点的数量。这里用到了类似线段树的lazy思想,区间成段修改直接打个标记,等到要划分这个区间的时候先把...
阅读全文
摘要:求把一个数拆成N个非1的数相乘的方案数有多少种(顺序不一样的算不一样的)。 如果不考虑是否为1的方案数,对原数所有的质因数直接用插板法然后乘起来就可以了,麻烦的是有一个所有数都不能为1的问题,这里可以用容斥原理组成。用f(i)表示有i~N个1的方案数,用x[i]表示确切有i个0的方案数。我们可以得到如下方程组:f(0)=1x[0]+1x[1]+1x[2]+1x[3]+....;f(1)= 1x[1]+2x[2]+3x[3]+....;f(2)= 1x[1]+3x[3]+...;f(3)= 1x[3]+...; 比如在算f(1)的时候,假设有3位数,我们枚举每一位为1,会产生重复的情况...
阅读全文
摘要:给出N个点,生成每条边的概率是pi,问生成一幅连通图的期望。 一开始正着想,感觉很复杂,无从下手,看了题解才发现原来是反过来思考的。。d[i]表示生成i个点的连通图的概率,那只要求出对应的不连通的概率,然后一减就可以了。生成不连通图的情况,就是从i-1个点中,选出1~n-1个点,选出的点和i连通而和其它点不连通,把所有的概率加起来就是生成不连通图的概率。。 1 #include <string.h> 2 #include <stdio.h> 3 #include <math.h> 4 int n; 5 double p, d[30], c[31][31];
阅读全文
摘要:这个模型跟小时候玩的大富翁棋类游戏差不多,起点是0,终点是N,每次掷骰子走1~6步,格子分为3种,前进1~6格,后退1~6格,以及停止一回合,求到达终点所需回合数的期望。 用E(I)表示从第I个格子走到终点所需回合的期望,E(N)=0,转移方程为 E(I)=sum(1/6*(E(K1)+1))+sum(1/6*(E(K2)+2))。K1,K2都是从I掷1~6能走到的格子,如果这个格子有操作,就要跳到操作后的格子,第一个sum里求的是不会停一回合的期望和,第二个sum里求的是走到停一回合格子的期望和。 因为有后退操作,所以转移是有环的,不能用记忆化搜索,要用高斯消元来做。 一开始可以D...
阅读全文
摘要:给出N个点M条边,每次等概率的给这张图加一条边,求连通这个图加边次数的期望。 这题我们并不关心图的形状,只要知道图的连通情况即可,即这张图有几个连通块,每个连通块中有几个顶点。比如,我们用E(2,3,3)表示当这个图有3个连通块,每个连通块中的顶点数分别是2,3,3时,我们把它连通所需加边的期望,对于8个顶点的图,E(8)=0。可以得到转移方程 E(2,3,3)=p1*E(2,3,3)+p2*E(2,6)+p3*E(3,5)+1。 把右边的第一项移到左边,然后用记忆化搜索就可以求解了。 其中p1,p2,p3是转移到其它连通情况的概率,在8个点里连一条边,总的方案数显然是C(8,2)...
阅读全文
摘要:给一个有向图,每个顶点的出度为1,A和B是图中的两个顶点,A和B每次只能走一步或者不走,设他们相遇时A走了X步,B走了Y步,使max(x,y)最大,有多解时,使min(x,y)最小,如果还有多解,使x>=y。 其实这个图最特殊的地方就是它每个顶点的出度仅为1。我们都知道树的特性是除了根节点外每个顶点的入度为1,那我们把这个图全部建反向边,也就是说每个顶点的入度为1。但是这个图是有环的,它没有入度为0的根,如果我们把环缩成一个点的话,就会发现这个环的整体入度为0,因为每个点在构环的时候入度就已经饱和了,同样,我们也很容易证明每个连通块至多只有一个环,因为一个连通块不可能有两个入度为0的点,
阅读全文
摘要:按S+W排序即可。 1 #include <stdio.h> 2 #include <string.h> 3 #include <algorithm> 4 #define MAXN 100005 5 typedef long long LL; 6 struct ppp{ 7 int s, w; 8 bool operator < (const ppp& p) const { 9 return s + w <= p.s + p.w;10 }11 }p[MAXN];12 int n;13 int main() {14 while (scanf
阅读全文
摘要:求用一个串的四个子串能覆盖原串的最大和最小长度。 比赛的时候没有出这一题,其实思路上差不多都是对的,但细节上没有实现好。。 三维的字符串DP,首先处理出每个子串能够开始的位置,这个暴力一下就行。然后用d[i][j][k]表示长度为i状态为j从当前位置开始已经有k个字符被覆盖的最小长度,j是个四位的二进制状态,为1代表已经使用了这个串。当前位置可以选择使用或者不使用新的未使用子串,DP的时候采用刷表会好写的多。 最小和最大的求法是一样的,开两个数组会爆空间。。改用short就行了。。其实写个函数也挺方便的。。 1 #include <string.h> 2 #include <
阅读全文
摘要:求一个K进制下是N的倍数的数,要求这个数使用的数字最少,数字个数相同时取较小的数。 首先有一个结论,至多用两个数字可以构造任意数的倍数。假设只有一个数字吗,由这一个数字构成的数模N的结果只能是0~N-1,由抽屉原理可知必然存在两个数模N的结果相同,这两个数一减,结果有两个数字构成,模N的结果是0。 然后就暴力BFS吧,队列中存的是余数,找到余数为0或者出现已经出现过的余数就返回。每次找到解比较跟新一下即可。 1 #include <string.h> 2 #include <stdio.h> 3 #define MAXN 10005 4 int n, k, num[2]
阅读全文
摘要:又是POJ原题,这网赛是有多少原题。。一些人站队,但有的一排站了多个人,每个人告诉你他前面有多少个人,后面有多少个人,问说实话的人最多有多少个。 比赛的时候没想法,大叔过的这一题。赛后看了解题报告才发现思想原来是那么简单。p[i][j]表示说前面i个人,后面j个人这个区间说实话的最大人数,有一个人说i,j就加一,注意不能超过n-i-j,然后d[i]表示i前面区间都已经确定时说实话的最大人数。d[i]=max(d[j]+p[j][n-i])。 1 #include <stdio.h> 2 #include <string.h> 3 #include <algorit
阅读全文
摘要:据说也是原题,N个人,F种食物,D种饮料,每种食物和饮料都有一定的数量,而每个人都有自己喜欢的食物和饮料,当一个人拿到自己喜欢的食物之一以及喜欢的饮料之一时,这个人能够被满足。求最多能满足多少人。 看到题就觉得是网络流,但一时没想到怎么建图,斌牛一看题就说是原题,然后啪啪啪敲完键盘就过了。。 食物放左边,饮料放右边,人放在中间,拆成两个点,点间流量为一,然后左点连喜欢的食物,右点连喜欢的饮料,再加个源点和汇点,做一遍网络流就OK了。。 1 #include <string.h> 2 #include <stdio.h> 3 #include <algorithm&
阅读全文
摘要:求g(g(g(n))) mod 109 + 7,已知g(n) = 3g(n - 1) + g(n - 2),g(1) = 1,g(0) = 0。 因为每两个数只和前两个数有关,所以模之后必然会出现循环节。现在只知道最外层的循环节,所以要把内两层的循环节暴力出来。有了三层的循环节之后用二分矩阵就可以了。 1 #include <string.h> 2 #include <stdio.h> 3 typedef long long LL; 4 struct matrix{ 5 LL mz[2][2]; 6 void init(int type){ 7 memse...
阅读全文
摘要:图上的每个点有权值,求使从起点无法到达终点去掉的权值和最小。 因为权值在点上,所以要进行拆点。将i点拆为2i和2i+1。然后流量统一从偶数点进,奇数点出,点之间连流量为点权的有向边,无向边拆成两条有向边,分别向两个端点连两条流量为无穷大的有向边,如下图所示。 1 #include <string.h> 2 #include <stdio.h> 3 #include <algorithm> 4 #define MAXN 500 5 #define MAXE 100000 6 #define INF 0x3f3f3f3f 7 struct edge{ 8 int
阅读全文
摘要:维护一个可以插入删除的有序序列,每次询问序列中位置mod5=3的数的和。 CodeForces原题,因为时限给的太宽,数据太水,STL可以暴力过。 用线段树和平衡树都可以做这题,线段树需要先离散化,然后每个区间五个标记分别保存到这个区间左端点的距离mod5=0~4的和,以及一个标记保存这个区间数的个数。合并区间的时候,左儿子因为左端点相同可以直接合并,而右儿子需要推一下,假设左儿子有Num个元素,右儿子本来Mod5=K的点,合并之后到左端点Mod5的值为(num%5+K)%5,所以sum[p][i] = sum[p<<1][i] + sum[p<<1|1][(i-num
阅读全文
摘要:直接map就水过去了。。 1 #include <map> 2 #include <string> 3 #include <stdio.h> 4 #include <iostream> 5 using namespace std; 6 map<string,int> mp; 7 string s[5005],s1; 8 int cas,n,m,cc[]={2,2,2,3,3,3,4,4,4,5,5,5,6,6,6,7,7,7,7,8,8,8,9,9,9,9}; 9 main(){10 for(cin>>cas;cas--;
阅读全文
摘要:这题比较容易想到的做法是splay,但是splay写起来比较麻烦而且每次操作都有LogN的复杂度,双向链表也是可以实现的,但实践起来比较麻烦,尤其是翻转操作。。。 可以发现每次L或者R都是移动一位的,我们可以用更简单的数据结构来实现,用两个栈分别存L左边和R右边的数据,L和R中间的数据使用一个双端队列来保存,因为涉及到翻转操作,要用一个dir来表示当前的双端队列哪边是头哪边是尾。。。 对于题目中给出的七种操作,都可以在O(1)的复杂度内实现,为了描述方便,左栈代表L左边数的栈,右栈代表R右边数的栈。 1,MoveLeft L/R 左移左指针就是把左栈中栈顶的数弹到双端队列头部,左移...
阅读全文
摘要:给出N个城市,城市之间的路径需要一定的花费。其中一些城市(H<=15)是必达的,在这些城市可以打工赚钱,但前提是有足够的钱购买这些城市的工作许可。问是否能获得所有的许可并且最终回到起点。 这题和我之前出过的一个题很像。。http://acm.csu.edu.cn/onlinejudge/problem.php?id=1175 先对这H个点做一遍最短路,这题的点比较少,直接用FLOYD,然后对这H个点用哈密顿回路DP就可以了。 需要注意的是一个城市允许经过多次,如果第一次来这个城市时不够钱购买工作许可可以在其他城市工作赚了钱之后再回来拿。。。 1 #include <string..
阅读全文
摘要:有一个栈,你可以把这个栈中的数吐到另一个栈中去,然后每次可以从两个栈中选择一个数出栈,使∑num[i]*(i-1)最小,num[i]代表第i个出栈的数。 比赛的时候一直没想法,看了解题报告才恍然大悟。。对于每个区间,枚举第一个人是第几个出栈的,假设区间是[L,R],第一个人是i个出栈的,那么这个栈就被分成了三部分,[L,L],[L+1,L+i],[L+i+1,R],对后面两个区间看作子问题继续DP,注意对后面一个区间要加上(sum[R]-sum[L+i-1])*i,sum[i]表示前缀和。 1 #include <stdio.h> 2 #include <string.h&g
阅读全文
摘要:求X^Z+Y^Z+XYZ=K有多少正整数解。 对于Z=2时是完全平方数可以直接求解,Z=3~31时直接暴力枚举即可,对于所有的X^Y可以全部预处理出来,最多大概也就50000*31种组合。 其实确定了X和Z后,Y可以二分求解的,但当Z>=3时Y能取的值加起来也没有多少。。所以枚举就OK了。 1 #include <stdio.h> 2 #include <math.h> 3 #define MAXN 47000 4 typedef long long LL; 5 const LL INF=(1LL<<31); 6 LL p[47000][31],k;
阅读全文
摘要:给出N个点,第一个点是裁判,其他N-1个点需要裁判过去回答问题,每个点需要的时间不一样,而每个裁判最多能回答M分钟的问题。题目分两问,第一问是如何分配可以使使用的裁判数最少,第二问是如何分配裁判,使裁判走过的总路程和最少,裁判一开始都在1,最终也要回到1。 至于第一问,用一个状态标记已经回答过的人,并用两个数组存回答这些人问题需要的最小裁判数以及裁判数最少时最后一个裁判的剩余时间,然后用类似哈密顿回路形式DP求解就可以了。 第二问,是MTSP(多旅行商)问题,先求出裁判走过每个集合最终回到起点所需走的路程,然后DP合并环即可。比如1~3三个点,裁判在1,那答案就是Min(1->2->
阅读全文
摘要:平面图网络流,比赛的时候想不到怎么建对偶图试了试dinic,居然水过去了。。数据是真水。。 赛后看了各牛的解题报告,才搞懂怎么建对偶图,确实是很巧妙。关于对偶图的概念,可以去看08年周东的论文《两极相通——浅析最大—最小定理在信息学竞赛中的应用》。 建对偶图的难点在于确定每条边相邻的是哪两个块,过程可分为四步 1、将无向图的每条边拆为两条有向边,然后扫描所有的点,将某边对于该点的入边ID和出边ID以及极角存起来。注意起点和终点之间也要连一条边。 2、将与该点相连的边按照极角排序,每条边的入边ID的next指向下一条边的出边ID。不难发现,这样操作以后,每个块周围的边形成了一个环,并...
阅读全文
摘要:网赛第一个看的就是这题,直接打表找规律。很容易发现是由大于4的的偶数以及奇数的平方,再除去偶数的平方所组成。一开始犯了个比较2的错误,要不然应该是FB了。。 也没有去推为什么是这样,这种题目一般都是先打表找下规律,一发现规律就懒的去推了。。 直接sqrt是有精度问题的,但是G++能A,C++是WA,比较简单的办法是sqrt后再通过乘法调整一下。 1 #include <string.h> 2 #include <stdio.h> 3 #include <math.h> 4 typedef long long LL; 5 int cas; 6 LL l,r;
阅读全文
摘要:8进制转10进制,只是对应位的数不一样。 1 #include <string.h> 2 #include <stdio.h> 3 int n; 4 int d[]={0,1,2,0,3,4,5,6,0,7}; 5 int main(){ 6 while(scanf("%d",&n),n){ 7 int sum=0,b=1,nn=n; 8 while(n)sum+=d[n%10]*b,b*=8,n/=10; 9 printf("%d: %d\n",nn,sum);10 }11 return 0;12 }
阅读全文
摘要:给出M个短串,这些短串由前N个大写字母组成。然后随机的按字符生成字符串,每次生成1~N个字符的概率是相等的,当生成串包含任意一个指定短串时,就停止生成。问生成串的长度的期望是多少。 首先建立Trie图,对每个可能作为短串结束的点都打上标记。用E(x)表示从这个点走到停止生成所需长度的期望。显然,对于打标记的点,E(x)=0。对于没打标记的点E(x)=∑(E(next[x][i])*1/N)+1(0<i<N),next[x][i]是它在trie图中接受字母i后走到的点。 然后根据Trie图建立方程组,用高斯消元求解E(0)即可。 高斯消元的精度着实很低,现在的代码能过G++,但C++
阅读全文
摘要:求从L~R转换成B进制之后数位之和为M的数有多少个。 国家集训队09年的论文《浅谈数位类统计问题》对这一类的问题总结的比较详细,数形结合的思想十分巧妙。 第二种查询要用到第一种查询的结果,然后二分一下就可以了。 1 #include <string.h> 2 #include <stdio.h> 3 #include <string.h> 4 typedef long long LL; 5 int q,x,y,b,m,k; 6 int d[32][301],num[32]; 7 int dp(int l,int s){ 8 if(s<0)return
阅读全文
摘要:很黄很暴力的枚举,加上了状态压缩的优化。 用15位的状态压缩木棍,1代表使用,0代表没有使用。然后枚举1~2^15作为一根木棍的组成,取反后的状态为令两根木棍,再枚举这个状态的所有子集,即将它拆成两根木棍。。。然后HASH一下就可以了。 其实是有重复状态的,每种状态都会重复六次。加上一个优化if(len[i]>=len[ii])continue;当第一条边比剩余两条边的和都大的时候就不去枚举剩余两条边的组合,这样效率会高上很多。 1 #include <stdio.h> 2 #include <string.h> 3 #include <algorithm&
阅读全文
摘要:把1~N的路径处理出来,算出需要的时间,如果时间不够就直接挂了,时间多的话就可以去用这些时间去拿别的物品了。 对1~N这条路径上的所有点做一遍树形背包,注意背包时不要背到这条路径上的点,否则就重复计算了。最后再将路径上的点用背包合并即可。 不过我这么写效率好像比较慢,跑了150ms+ ,rank上有不少0ms的,应该是有更好的算法。。 1 #include <stdio.h> 2 #include <string.h> 3 #define MAXN 105 4 struct edge{ 5 int v,w,n; 6 }e[MAXN*2]; 7 int first[MAX
阅读全文
摘要:用一个最小值和最大值来表示每个节点的范围,DFS一遍即可。父亲节点的最小值必然比儿子节点的最小值之和大1(它自身至少要1元),至于最大值,没有什么限制,我一开始一直WA在这里了,因为儿子最大值的和是限制不了父亲节点的,因为父亲节点可以取任意大的值。。最后每个节点的最小值都一定小于等于最大值才会是正确的。。 1 #include <stdio.h> 2 #include <string.h> 3 #define MAXN 10005 4 typedef long long LL; 5 const LL INF=100000000000LL; 6 struct edge{
阅读全文
摘要:几何模版题。三维凸包+多边形重心+点面距离。模版一拼就过了。 纯模版这种东西就不贴了。。。
阅读全文
摘要:之前贪心的想法确实是错误的,比赛的时候数据太水了,过了也就没有想那么多了。如果误导了他人,实在是抱歉。 对于每个元素,最坏情况下它只能够到它后面的第9个数字,因为最坏情况下,它后面的四个数字能被它前面的四个数字消掉,这样它就能和原来是它后面的第9个元素相消了,于是我们可以用d[i][st]表示第i个数字,从i开始的10个数字的状态为st时是否可消。之后记忆化搜索即可。 状态转移比较简单,如果st的第1位为0,说明这一位已经被消掉,d[i][st]=dp(i+1,next(st))。如果第1为为1,向后连续找至多五个为1的位,比较是否和第一位数字相同,如果相同,就将st的这两位置为0,然...
阅读全文
摘要:这么水的一道最短编辑距离DP,比赛的时候居然没有去做。。 很裸的最短编辑距离DP,就是要注意环的问题。因为如果直接copy两遍的话,有可能会将本来是同一个位置的字母使用两次。但是可以发现串的长度只有10,最大的编辑距离不会超过10,当原串长度>2*L时环就没有影响了,因为这时如果环中一个字母被使用两次,那最短编辑距离肯定已经大于L了。 我是长度小于20时暴力枚举,大于30时在原串后面copy原创的前20个字符。 1 #include <stdio.h> 2 #include <string.h> 3 #include <algorithm> 4 #de
阅读全文
摘要:就是一道比较麻烦的模拟题,比赛的时候没有敲,赛后1A了。。 其实主要是输入比较麻烦,买东西合成物品什么的暴力一点也不会出错的。 代码写的后丑,A了之后也懒的改了。。 1 #include <string.h> 2 #include <stdio.h> 3 #include <string> 4 #include <sstream> 5 #include <iostream> 6 using namespace std; 7 struct equip{ 8 string name; 9 int val,type; 10 string m
阅读全文
摘要:贪心,用set水过。 先按x,后按y排序,都想等时Bob放前面。然后扫一遍遇到Bob就将卡片的y值放入set中,遇到Alice就在集合中找一个能被他覆盖的y最大的数,将它擦去。因为如若能覆盖而不去覆盖了就等于浪费了这个,所以必然选择用掉这张卡片。最后统计一共成功覆盖了多少个即可。 1 #include <string.h> 2 #include <stdio.h> 3 #include <algorithm> 4 #include <set> 5 #define inset multiset<int,greater<int> &
阅读全文
摘要:根据%k=a中a和k的不同组合建立55棵树状数组,每次修改操作只对其中1棵树状数组进行操作,每次查询对其中10棵树状数组统计增量和。 1 #include <string.h> 2 #include <stdio.h> 3 #define MAXN 50005 4 int n,q,x[MAXN]; 5 int ta,tb,cc,k,op; 6 int c[55][MAXN]; 7 inline void update(int *c,int x,int d){while(x<=n)c[x]+=d,x+=x&-x;} 8 inline int query(in
阅读全文
摘要:题目问用1*2组成如图h*w矩形的方案有多少种。 明显的状态压缩DP,从上向下填充,假设两行的状态为stat1和stat2,则需要满足的条件是stat1|sta2=1<<w-1以及stat1&stat2中连续的1都是偶数个。因为上一行为空的下一行必须放一个竖的,而除去竖着到上一行的都是横着的,每一个横着的占的宽度都是2,所以stat1&stat2中连续的1肯定是偶数个。 对每一层要记录一个状态是否搜过,并记录这个状态有多少种方法,即记忆化搜索。复杂度是O(h*(2^w)*(2^w))。 斌牛的方法更为高效简洁,状态表示的是当前轮廓线的状态,复杂度是O(h*w*(2^
阅读全文
摘要:KD树,来源计算几何,在《计算几何-算法与应用》一书中有详细的解释。 这题是比较裸的KD树模型,要在点集中找到离一个点最近的一个点。其实KD树就是一棵多维平衡二叉树,将多维空间分成很多个部分,查找时能够较快的逼近查找点,从而快速的找到距离某点最近或者较近的点。 在网上找到了这份模版,简洁高效。 MARK一下URAL1369,也是一道KD树,目前TLE中。。。 1 #include <stdio.h> 2 #include <string.h> 3 #include <algorithm> 4 #define MAXN 100005 5 #define INF
阅读全文
摘要:为了做份高斯消元的模版做了这一题,模版来自http://www.cnblogs.com/kuangbin/archive/2012/08/31/2666144.html。 但这份模版中求自由元的部分应该是错误的,从下向上枚举肯定是不对的,比如x+y+z=10,y+z=5,这个方程组中x实际上是确定的,但这份模版会将x识别为不确定元素。 其实本来是想找份要求自由元的题目的,但还没找到。这题是求同余方程组,跟一般的高斯消元差不多,只是要在消元过程中注意模的问题,另外最后答案要通过扩展欧几里德求出。 继续去找要求求自由元的题目。。 1 #include <string.h> 2 #inc
阅读全文
摘要:一个n*m的矩形,给出从每个点去它周围的四个点的概率,问从[1,1]走到[n,m]的所花步数期望是多少。 在汤可因的国家集训队论文《浅析竞赛中一类数学期望问题的解决方法》中提到了这个题,对这种带环的模型一般都是高斯消元求解。 假设从某个点走到终点所花步数的期望是d[i,j],很容易推出方程: 这样对每个点列出一个方程,一共n*m个未知数,n*m个方程,用高斯消元即可求解,但是如果直接高斯消元复杂度会达到O(n^3*m^3),所以必然要在基础的高斯消元上加以优化。 下面的这张图片取自题解,是当n=3,m=4时所列出的矩阵,题解中提到了一个block tridiagonal m...
阅读全文
浙公网安备 33010602011771号