51nod
文章平均质量分 65
一些51nod的题目题解
扩展的灰
扩展的灰(Extended Ash)
展开
-
51Nod1514 美妙的序列
题目看这里需要开一个新的分类了,生成函数相关这道题确实非常的入门分析得知,不合法方案就是存在一个i那么设f[n]表示n的答案,可以得到f[n]=n!-∑f[i]*(n-i)! (i移项得到∑f[i]*(n-i)!=n! (i发现可以生成函数设F(x)=∑f[i]*x^i, G(x)=∑i!*x^i (i=1..∞)根据上面那条式子得到F(x)*G(x)=G(x)-原创 2018-04-23 16:10:09 · 424 阅读 · 0 评论 -
51nod1122 机器人走方格V4
题目看这里看一看知道可以dp设f[i][s1][s2][s3][s4]表示走了i步,每个机器人分别在哪个格子里用矩阵优化但是发现状态数过于巨大,会TLE考虑设f[i][j][k]表示走了i步,从j格子走到k格子的方案数那么显然f[i]=T^i 其中T是全1矩阵减掉单位矩阵那么可以快速幂求出f接下来枚举4的全排列g,表示第i个机器人走到g[i]答案就是∑∏f[i]原创 2018-04-27 11:49:53 · 267 阅读 · 0 评论 -
51Nod1294 修改数组
题目看这里一个非常好的结论题发现题目要求要严格递增而且要求要正整数,所以直接做LIS不行我们令原序列s变为s[i]-i那么如果s[i]-i是一个负数,肯定不符合题意答案加一去掉所有负数以后,就可以对s做一个LIS了,这里LIS可以是严格非降的就可以了#include#include#include#define inf 0x7f7f7f7fusing names原创 2018-04-27 16:16:29 · 264 阅读 · 0 评论 -
51Nod1084 矩阵取数问题 V2
题目看这里一个经典的dp题,典型的错误思想就是做两遍我们考虑直接做,f[i][j][x][y]表示第一次取道i,j这个位置,第二次到了x,y这个位置考虑这个i,j和x,y分别是从哪里转移过来,就可以得到方程f[i][j][x][y]=max(f[i-1][j][x-1][y],f[i][j-1][x-1][y],f[i-1][j][x][y-1],f[i][j-1][x][y-1]原创 2018-04-27 17:03:02 · 323 阅读 · 0 评论 -
51Nod1120 机器人走方格 V3
题目看这里一个数学题,答案就是卡特兰数*2求卡特兰数要用到组合数求法f[n]=C(2n-2,n-1)/n由于模数较小,可以Lucas定理直接做,但是这样是有问题的因为n不一定和模数互质,但是还是A了,数据比较水#pragma GCC opitmize("O3")#pragma G++ opitmize("O3")#include#include#include#def原创 2018-04-27 17:10:46 · 305 阅读 · 0 评论 -
51Nod1158 全是1的最大子矩阵
题目看这里想到了NOIP普及组当年那道题做法非常显然,O(n^2)枚举矩形的上下边界,让后用一个dp+前缀和就搞定了f[i]表示以第j列作为结尾的最大子矩形的宽,那么如果第i列在[l,r]的范围都是1,那么f[i]=f[i+1],否则f[i]=0答案就是max{(r-l+1)*f[i]}#pragma GCC opitmize("O3")#pragma G++ opitm原创 2018-04-27 17:19:44 · 293 阅读 · 0 评论 -
51Nod1204 Parity
题目看这里+一看求和就知道是要先用前缀和的让后看到类似相等和不相等的条件,可以考虑并查集当然这道题由于变量的值一定是0,1所以关系只有不等号也有反传递性,可以直接拆点来做如果s[i]=s[j]那么我们就将i,j所在的并查集合并,将i'和j'所在的并查集合并否则我们将i'和j合并,i和j'合并当一次合并之后发现i和i'在同一个集合里时,直接输出退出#pragma GC原创 2018-04-27 17:29:45 · 241 阅读 · 0 评论 -
51Nod1215 数组的宽度
题目看这里各种求和最好玩的啦看到题目就应该知道要单独考虑每个元素的贡献那么一个元素i的贡献肯定是a[i]*(l[i]-i)*(i-r[i]),这里l,r分别表示左边和右边第一个比i大的数的位置最大值部分的贡献算完了最小值是类似的考虑怎么求这个l和r,直接上单调栈就可以了(code很难看当时不知道在想什么写成这样)#pragma GCC opitmize("O3")原创 2018-04-27 17:38:05 · 252 阅读 · 0 评论 -
51Nod1225 余数之和
题目看这里数论好题我们以前在做反演的时候,常常用到一个叫做分块除法的东西具体来说,[n/i]只会有不超过√n种取值那么这题也可以这样做 因为n%i=n-[n/i]*i我们可以对i分块,对于[n/i]取值相同的一起计算,那么每次就是一个等差数列求和,总复杂度O(√n)#include<stdio.h>#include<string.h>#include<algori...原创 2018-04-27 19:45:24 · 249 阅读 · 0 评论 -
51Nod1257 背包问题 V3
题目看这里01分数规划入门题这道题有非常经典的错误解法:按照pi/wi排序这样是不能保证答案最大的,反例(本体样例)已经有了那么我们来考虑怎么做首先我们二分这个答案ans让后我们给每个物品i设置一个权值v[i]=p[i]-ans*w[i]所有物品按照v排序,取前k大求和那么如果ans是正确答案,那么显然,这个和S=0如果ans大于正确答案,S如果ans小于正原创 2018-04-27 20:00:48 · 231 阅读 · 0 评论 -
51Nod1353 树
题目看这里题意很简单,大概是有多少种删边方法使得每一块大小不小于k我们设一个树形dp,f[i][j]表示i的子树中,i所在联通块的大小为j的方案数有多少特别的,我们用f[i][0]表示∑f[i][j] (j>=k)那么可以写出以下转移:f[x][i+j]+=f[x][i]*f[v][j] (j>0)f[x][i]=f[x][i]*f[v][0]答案就是f[root][0]#includ...原创 2018-04-27 21:08:43 · 310 阅读 · 0 评论 -
51Nod1537 分解
题目看这里基于一个思想,如果x=y+1 那么一定有x%M=y+1%M可以发现1+√2和复数有着类似的运算法则,可以用快速幂加取模来计算所以我们考虑用几个不同的模数来判断,如果都有x=y+1,那么就可以认为问题有解#pragma GCC opitmize("O3")#pragma G++ opitmize("O3")#include<stdio.h>#include<stri...原创 2018-04-27 21:42:02 · 218 阅读 · 0 评论 -
51Nod1364 最大字典序排列
题目看这里一道比较简单的贪心题容易想到从前到后确定每一位我们可以用一个splay来维护当前未确定的部分的顺序假设当前剩下k次操作机会那么我们可以求出splay中前k+1个元素中的最大元素i,令k减少rank(i),让后将其输出并从splay中删掉最后k=0时,输出splay中剩余元素比题解那个线段树好写多了,主要是不用想,而且splay还挺快的#include<stdio.h>#in...原创 2018-04-27 22:03:39 · 277 阅读 · 0 评论 -
51Nod1022 石子归并V2
题目传送门四边形不等式第一题,口胡一下我们原来的方程式:f[i][j]=sum[i][j]+max(f[i][k]+f[k+1][j]){i那么,如果我们将最优的那个k记录下来,记为g[i][j],那么必然会有g[i][j-1]当然这个东西成立是需要条件的,就是f[i][j']+f[i'][j]f[i][j]+f[i'][j'] (i博主太弱上面两个都不会证明(只会证明sum[原创 2017-12-02 16:37:42 · 251 阅读 · 0 评论 -
51Nod1469 淋漓尽致子串
首先,我们来定义一下淋漓尽致子串。1.令原串为S。2.设子串的长度为len,在原串S中出现的次数为k,令其出现的位置为p1, p2, ....pk(即这个子串在原串中[pi,pi + len - 1]中出现)。3.若k=1,则该子串不是淋漓尽致子串。4.若存在pi,pj(i != j),使得S[pi - 1] = S[pj - 1],则该子串不是淋漓尽致子串。5.若存在pi原创 2018-02-07 09:27:26 · 275 阅读 · 0 评论 -
51nod1485 字母排序
题目看这里也是非常简单的线段树合并模板题了,虽然实际上最好的做法因该是开数组合并(这样是均摊O(1)的)不过还算跑的快,第四#pragma GCC opitmize("O3")#pragma G++ opitmize("O3")#include#include#include#define mid (l+r>>1)#define N 100010using names原创 2018-02-15 09:26:28 · 221 阅读 · 0 评论 -
51Nod1349 最大值
题目看这里 各种离线套路题。。。我们考虑对每个元素都先预处理答案让后就可以O(lg n)回答了将元素排序后,对于两个询问i,j∈(s[k],s[k+1]]的答案是一样的,我们考虑计算当i=s[k]时的答案显然,当i=s[1]的时候,答案就是总区间数这时考虑当i->s[2]的时候有哪些区间被从答案中去掉了对于一个点i,令l[i]表示当前询问q下,满足区间[l[i],i]最大值原创 2018-02-15 09:41:21 · 305 阅读 · 0 评论 -
51Nod1444 破坏道路
题目看这里也是非常套路的一道题首先考虑,如果只有一组限制,那么答案就是m-l1现在考虑加了一组限制的情况下有什么影响显然,被两段路径重复覆盖的那一部分会多减掉一次那么我们可以枚举这段路径,让后用dp来计算答案,注意因为是无权图可以bfs O(n^2)求出两点之间最短路#pragma GCC opitmize("O3")#pragma G++ opitmize("O3"原创 2018-02-15 10:16:10 · 333 阅读 · 0 评论 -
51Nod1207 内存管理
题目看这里这么好玩的数据结构题肯定是要来做一做啦考虑splay-显然用一个节点去维护一个连续的内存块,每次申请内存就找一块尽可能前的,释放就找一个有相交的并合并,没有则新建节点splay一打还是错落百出,不过效率还是可以的,跑了第一和map一样快#include<stdio.h>#include<string.h>#include<algorithm>#d...原创 2018-02-19 10:17:54 · 301 阅读 · 0 评论 -
51Nod 1052/1053/1115 最大M子段和V1/V2/V3
V1N个整数组成的序列a[1],a[2],a[3],…,a[n],将这N个数划分为互不相交的M个子段,并且这M个子段的和是最大的。如果M >= N个数中正数的个数,那么输出所有正数的和。N,M例如:-2 11 -4 13 -5 6 -2,分为2段,11 -4 13一段,6一段,和为26。V2N个整数组成的序列a[1],a[2],a[3],…,a[n],将这N个数原创 2018-02-21 00:06:37 · 392 阅读 · 0 评论 -
51Nod1556 计算
题目看这里一个公式题,推不出来我们令f[i]表示当n=i时的总方案数,令g[i]表示n=i时,结尾恰为1的方案数那么显然,f[i]=3f[i-1]-g[i]只需要考虑计算g[i],这个东西是一个叫做默慈金数的东西递推式为g[n+1]=g[n]+Σg[i]*g[n-i-1]=((2n+3)*g[n]+3n*g[n-1])/(n+3)直接计算即可#pragma GCC原创 2018-02-22 21:21:28 · 268 阅读 · 0 评论 -
51Nod1678 lky与gcd
题目看这里本来以为是一个离线做的题目结果发现数据小可乱搞预处理f[i]表示Σa[ki],预处理每个i的因子集合s[i]每次修改位置i,即为将所有的f[s[i]]都修改每次求和,答案为Σmu[i]*f[i] mu为莫比乌斯函数复杂度O(n√n)#pragma GCC opitmize("O3")#pragma G++ opitmize("O3")#includ原创 2018-02-22 21:28:52 · 252 阅读 · 0 评论 -
51Nod1426 沙拉酱括号
题目看这里我们考虑怎样得到最大答案首先对原序列进行括号配对,没有配对上的那些可以直接扔掉不影响答案让后我们有一个合法的括号序列当一对括号与区间有相交但是不包含整个区间时,将会产生一个位置的浪费(在区间内的那个左括号或者右括号没法配对了),所以答案-1那么一个区间的答案[l,r]应该是r-l+1-与这个区间相交的括号对数+包含这个区间的括号对数(会被减重)求相交的个数可以前缀原创 2018-02-22 21:41:02 · 229 阅读 · 0 评论 -
51Nod1679 连通率
题目看这里一个简单的计数问题我们先考虑O(n^2)的做法对每个点dfs一次,求出d[i]表示i的深度,那么对答案贡献就是Σ2^(n-d[i])那么我们考虑用数据结构动态维护这个d[i],显然可以用线段树来维护dfs序做到复杂度O(n lg n) 效率很高rank8看了下solution突然才发现别人都不是这么做的!不管了反正跑得过而且跑的快。。就是代原创 2018-02-22 21:51:15 · 256 阅读 · 0 评论 -
51Nod1528 加号分配
题目看这里考虑单独计算每个位置的贡献一个位置i的贡献为c[i]*10^k当且仅当它后面连续(k-1)个数前都没有加号那么也就是确定了k个位置的情况,剩下的位置未知,用组合数计算即可注意到当k相同时很多位置的系数是一样的,可以前缀和降低复杂度至O(n)#pragma GCC opitmize("O3")#pragma G++ opitmize("O3")#include原创 2018-02-22 21:59:04 · 279 阅读 · 0 评论 -
51Nod1442 士兵的旅行
题目看这里一看这种分配式的题目马上联想到网络流顺手一个SAP板子直接0ms上rank1拆点建图x,y1.s->x[i]边权a[i]2.y[i]->t边权b[i]3.对于原图每条边p->q,x[p]->y[q]边权∞4.x[i]->y[i]边权∞#pragma GCC opitmize("O3")#pragma G++ opitmize("O3")#inclu原创 2018-02-22 22:07:25 · 209 阅读 · 0 评论 -
51Nod1601 完全图的最小生成树计数
题目看这里这个题好像在哪里做过。。。但是翻不到基本思想:在最高位不同的两个集合里只能有一条边相连我们可以用trie来做,每次到一个节点,就在他的两个儿子里找xor值最小的加到答案里若有超过2个权值相同的点时,计算方案的方法为x^(x-2),这个是完全图的生成树个数公式无压力·真rank1#include#include#include#define N 10001原创 2018-02-22 22:29:28 · 512 阅读 · 0 评论 -
51Nod1295 XOR key
题目看这里经典的区间xor最大值问题很久以前就知道做法所以来写一写,可持久化trie意外地发现好写而且跑得很快#pragma GCC opitmize("O3")#pragma G++ opitmize("O3")#include#include#include#define N 50010using namespace std;int c[N*40],s[N*4原创 2018-02-27 21:56:26 · 341 阅读 · 0 评论 -
51Nod1395 两个回文
题目看这里复习一下PAM做两次回文自动机,一次正串,用f[i]表示以i结尾的串最长的回文子串反过来做一次记为g[i]那么ans=max(f[i]+g[n-i])#include<stdio.h>#include<string.h>#include<algorithm>#define N 100010using namespace std;char S[...原创 2018-02-27 22:06:51 · 293 阅读 · 0 评论 -
51Nod1502 苹果曼和纸
题目点这里漏写博客好多天了,赶快来补这道题是一个裸的模拟题,注意到纸片总长度不会增加,所以用一个带翻转的splay来维护一下每次将前半段翻转和后一段做加法合并就好了,均摊logn#pragma GCC opitmize("O3")#pragma G++ opitmize("O3")#include#include#include#define N 100010#defi原创 2018-03-22 21:33:48 · 258 阅读 · 0 评论 -
51Nod1553 周期串查询
题目看这里我们发现需要动态维护一个字符串是否成周期根据border的一个简单性质,得出周期串的充分必要条件是,如果a[i..k]=a[j-k+1..j] 那么a[i..j]是以k为周期的串于是可以用线段树来维护哈希莫名其妙rank1..#include#include#include#define N 100010#define LL long long #def原创 2018-03-22 22:05:51 · 319 阅读 · 0 评论