随笔分类 -  POJ

摘要:在10^4方内选4个数,这4个数的最大公约数是1,求方案数。 先求出所有这样的数x=p1*p2*p3..*pn,pi是不同的素数,并且d(x)=n。然后容斥原理即可 ans=C(n,4)+∑C(x,4)*(-1)^d(x)。 1 #include <stdio.h> 2 #include <string.h> 3 #include <algorithm> 4 #define MAXN 10005 5 using namespace std; 6 typedef long long LL; 7 int flg[MAXN], x[MAXN], maxx; 8 L 阅读全文
posted @ 2012-10-31 16:50 Burn_E 阅读(253) 评论(0) 推荐(1)
摘要:跟2010福州的现场赛那题基本一样的,只是多了个去重。。上半年在金华邀请赛的时候还不会AC自动机,今天突然想起来就找出来写了一下。。数据给的很大,不过空间给的也是巨大=。= 解码后就是裸的自动机,把包含的串标记一下,再用自动机找这些串的子串去重即可。 1 #include <string.h> 2 #include <stdio.h> 3 #define MAXN 3000000 4 int cas, n; 5 int pos, next[MAXN][26], fail[MAXN], id[MAXN], flag[MAXN]; 6 char s[MAXN*2], ss[ 阅读全文
posted @ 2012-10-04 21:44 Burn_E 阅读(458) 评论(0) 推荐(0)
摘要:给出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]; 阅读全文
posted @ 2012-09-21 22:12 Burn_E 阅读(297) 评论(0) 推荐(0)
摘要:这个模型跟小时候玩的大富翁棋类游戏差不多,起点是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... 阅读全文
posted @ 2012-09-21 12:12 Burn_E 阅读(432) 评论(0) 推荐(0)
摘要:给出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)... 阅读全文
posted @ 2012-09-21 11:15 Burn_E 阅读(701) 评论(0) 推荐(0)
摘要:为了做份高斯消元的模版做了这一题,模版来自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 阅读全文
posted @ 2012-09-02 17:48 Burn_E 阅读(272) 评论(0) 推荐(0)
摘要:为了学习高斯消元写了下这一题,代码是按照维基百科的伪代码来写的,每个点的状态和他自己以及周围五个点是否按下有关,于是只要每个点作为一个未知数,列出30个方程,用高斯消元求解即可。 其实这题完全可以不必用高斯消元,枚举第一行的状态就可以了,第一行的状态可以决定第二行的状态,进而就可以决定整幅图的状态。 1 #include <string.h> 2 #include <stdio.h> 3 #include <algorithm> 4 #include <stdlib.h> 5 int cas,n,m,x[50][50],ans[31]; 6 vo 阅读全文
posted @ 2012-08-31 19:22 Burn_E 阅读(289) 评论(0) 推荐(0)
摘要:为了理解期望DP做的第一道期望题。 一共有s个子系统和n个bug,一次能找一个Bug,求出在s个子系统中发现n个Bug的期望次数。bug是无穷的,所以认为每次在每个系统找找到一个Bug的概率是相等的。 这种题目基本都是设E(now)为从当前状态到达结束状态的期望,E(now)=∑E(x)p(x),x表示可以从now转移到的状态,p[x]表示转移到这个状态的概率。 1 /* 2 s个子系统,n个bug, 3 e[i][j],在i个子系统中发现j个bug到达目标的期望,显然d[s][n]=0; 4 e[i][j]可以转化成四种情况 5 发现无用的bug e[i][j... 阅读全文
posted @ 2012-08-31 10:16 Burn_E 阅读(264) 评论(0) 推荐(0)
摘要:应该算是最基础的AC自动机DP了吧。。 跟前面做的两道用矩阵加速的AC自动机题目意思差不多,都是求不包含给定单词的单词数。区别就是给定单词较多,需要的字符串比较短,然后结果不取模,要用到高精度。 trie图中大约有50*10个节点,如果建立矩阵用矩阵加速无论是时间复杂度还是空间复杂度都是会超的(时间大约是500^3*log(50),空间是500^2*高精度数组)。所以这里要用到DP了,用dp[i][j]表示第i步在第j个节点的方法数。flag[k]=0表示不是非法节点,son是k的儿子节点的集合。 一开始爆空间了,POJ真心抠啊,这题就给了10M内存,后来高精度里面用char存,... 阅读全文
posted @ 2012-08-07 10:26 Burn_E 阅读(258) 评论(0) 推荐(0)
摘要:又是一道调了大半天的题,最后发现竟然是自己建立trie图的地方有个小BUG,这个小BUG在字符串匹配时没什么影响,所以一直没发现出来。刚刚学习,还是理解的不够深入啊。现在这个trie图应该算是写的很简洁了,可以拿来当模版了。 题意很简单,就是问长度为n不包含若干子串的串一共有多少个。这里可以用AC自动机DP,首先对于单词的结尾节点,标记为非法节点,一旦走到了一个非法节点,就说明包含了某个单词。网上的解题报告很多人说是AC自动机DP。但这题我的做法似乎没有用到DP,只是用矩阵加速了一下罢了。。。。首先标记出非法节点,补全trie图,用一个矩阵表示从每个合法节点到其它合法节点转移的方案,可... 阅读全文
posted @ 2012-08-06 15:50 Burn_E 阅读(286) 评论(0) 推荐(0)
摘要:感觉是不太好想的一道题,看完之后能想到是KMP,按照自己的想法敲了出来,但一直过不了。后来在网上搜题解搜到了一篇国家集训队的论文《由图论问题浅析算法优化》,论文中提到了这道题,想法很巧妙,类似于枚举,再加上KMP的优化。因为S较小(1~25),只要枚举模式串中的数字和匹配串中的数字的对应关系并且满足大小顺序关系就可以确定下来这个子串是否符合要求,具体的过程可以去看一下论文,这个算法的本质还是枚举,只是在枚举中进行了优化,并且使用KMP优化来快速找到符合对应关系的子串的位置,我的程序在POJ上跑了一秒多点,应该可以再优化。 但是上面的算法还是有缺点的,其复杂度是O(S*S*(N+M)),当... 阅读全文
posted @ 2012-08-05 00:00 Burn_E 阅读(919) 评论(0) 推荐(0)
摘要:简单的KMP,考察对next数组的理解,next[i]表示S[1..i]中前缀和后缀的最大匹配程度。 假设字符串长度为L,用S[i..j]表示下标从i到j的字符组成的子串。 首先next[L]=x1,说明这个字符串S[1..x1]和S[L-x1+1..L]是相同的,所以x1是一个可能的公共前缀和后缀的长度值。然后next[x1]=x2,说明S[1..x2]和S[x1-x2+1..x1]是相等的,而S[1..x1]=S[L-x1+1..L],就有S[1..x2]=S[x1-x2+1..x1]=S[L-x2+1..L],所以x2也是一个可能的前缀和后缀的公共长度值,这样一直推到next[i... 阅读全文
posted @ 2012-08-03 13:08 Burn_E 阅读(184) 评论(0) 推荐(0)
摘要:这题是在做KMP分类里做到的,网上搜到的题解也基本都是KMP解的。但这题根本不是KMP,在网上找了个KMP的程序,随便rand了10组数据,跑了10多秒。 题意比较纠结,就是说给你一个长度为N的串S,找出S[k..k+t-1]=s[N-t+1..N],其中1<=t<=13,k<=N-t,有多个k满足时,选择t最大的并且最靠右的,令S[N+1]=S[k+t],如果找不到符合条件的的K,则S[N+1]='0'。 正解应该是压缩状态,每个子串都由01组成,可以看作一个2进制数,因为t的范围<=13,所以用2^13就可以表示出所有的子串,用last[i][j]表 阅读全文
posted @ 2012-08-03 11:31 Burn_E 阅读(446) 评论(0) 推荐(0)
摘要:一道KMP的好题,可惜数据实在是太弱了。 给出R*C的字符矩阵,问至少多大面积的小矩阵可以覆盖掉整个大矩阵。很容易想到的解法就是求出循环节然后求最大公倍数,但是这样就忽视了可以不用正好覆盖这个条件,比如aaabaa可以拆成aaab/aa,aaaba/a,aaabaa,而不一定非要拆成4的倍数。正确的做法是求出每一列可能拆分的长度,然后取所有列都可以分的长度中最小的。比如 abcdeaa aaabaaa 第一个串可以分的长度有5,7,第二个串可以分的长度有4,5,6,7,所以取5作为公共长度。至于怎么求一个字符串所有可以拆分的情况,用KMP处理一遍就可以了,然后从最后一列开始,取i=... 阅读全文
posted @ 2012-08-03 00:22 Burn_E 阅读(180) 评论(0) 推荐(0)
摘要:考察对KMP的next数组的掌握,next数组也就是失败指针指向它失败后应该指向的位置,next[i]~i之间就是一个循环节,所以只要满足i%(i-next[i])==0即可。#include <string.h>#include <stdio.h>int cas=1,n;char s[1000005];int next[1000005];void solve(){ next[1]=0; int len=strlen(s+1); for(int i=2,j=0;i<=len;i++){ while(j>0&&s[i]!=s[j+1])j=ne 阅读全文
posted @ 2012-08-02 23:27 Burn_E 阅读(155) 评论(0) 推荐(0)
摘要:给出一个字符串S1和S2,可以对S1进行添加字符(insert),删除字符(delete),替换字符(replace),交换相邻字符(swap)四种操作,问是否能在dis步骤内将S1转换成S2。 用d[i][j]表示将S1[1..i]转化为S2[1..j]的最小步数。 这几种操作可以表示为:添加d[i][j]=d[i][j-1]+1,删除d[i][j]=d[i-1][j]+1,替换d[i][j]=d[i-1][j-1]+1,交换d[i][j]=d[i-2][j-2]+1(条件为s1[i-1]==s2[j]&s1[i]==s2[j-1])。 但是仅考虑到这些还是过不了这道题的,因为交换. 阅读全文
posted @ 2012-08-02 14:35 Burn_E 阅读(453) 评论(0) 推荐(0)