摘要: /*采用树状数组加速程序思路是,分数无关,先排序,把index拿出来。满足条件的的 a b c编号必须是a < b < c或者 a >b > c所以对编号数组从左到右和从右到左扫描,计算出每个编号左边比自己小的个数,右边比自己大的个数,乘起来就是结果,当然还要加上反的情况。基本上可以算是O(n)把*/#include <cstdio>#include <cstdlib>#include <iostream>#include <cmath>#include <algorithm>#include <cstr 阅读全文
posted @ 2012-03-30 12:03 AC2012 阅读(390) 评论(1) 推荐(0) 编辑
摘要: /*最长回文子串算法manacher算法 O(n)线性算法当然也使用扩展的KMP算法 O(nlogn)*/#include <cstdio>#include <cstdlib>#include <iostream>#include <cmath>#include <algorithm>#include <cstring>using namespace std;#define MAXN 1000010char in[MAXN],in2[MAXN*2];int p[MAXN*2];int n,m;void init(){ in 阅读全文
posted @ 2012-03-28 22:00 AC2012 阅读(484) 评论(0) 推荐(0) 编辑
摘要: /*简单的sg游戏*/#include <cstdio>#include <cstring>int T;int N;int A[22],L[22];int sg[22];int dfs(int x,int m){ int& cur = sg[x]; if(cur!=-1)return cur; bool used[22] ={0}; for(int i=1;i<=m;i++) { if(x>=i) used[ dfs(x-i,m) ] = 1; } for(int i=0;;i++) { if(!used[i]) { cur = i;break; } 阅读全文
posted @ 2011-06-17 00:38 AC2012 阅读(325) 评论(0) 推荐(0) 编辑
摘要: /*无环图,树计算 sg值,求出每个节点处得sg值来*/#include <cstdio>#include <vector>using namespace std;int N,M,Q;int sg[1010];vector<int> G[1010];int dfs(int x){ int& cur = sg[x]; if(cur!=-1) return cur; cur = 0; bool used[1010]={0}; for(int t,i=G[x].size()-1;i>=0;i--) { used[ dfs(G[x][i]) ] = 1 阅读全文
posted @ 2011-06-16 23:51 AC2012 阅读(205) 评论(0) 推荐(0) 编辑
摘要: /*指定一个数 nn ~ oo 是必败态n/9 - n-1 必胜n/18 ~ n/9 必败n/(18*9) ~ n/18-1必胜态n/(18*18) ~ n/(18*9) 必败对于这个题目,很明显的需要用到必胜态和必败态来判断。而且n很大,所以不可能用数组求,所以只能找规律对于n及比n大的数是必败态所有能够转到必败态的状态都是必胜态所以n/9 ~ n-1就是必胜态了所有全部到达必胜态的状态是必败态所以n/18 ~ n/9 就是必败态,可以用一个区间来表示。这里需要注意边界,这里我没有考虑*/#include <cstdio>int n,ans;int main(){ while(s 阅读全文
posted @ 2011-06-16 14:08 AC2012 阅读(181) 评论(0) 推荐(0) 编辑
摘要: /*K个石块,L最大取值。问L取什么样的值,可以保证第二个选手赢1 ~ L 必胜L+1 必败L+2 ~ L+L+1 必胜L+L+2 必败L+L+3 必胜 L+L+2+L必胜L+L+L+3 必败4L+45L+5通过找规律发现,必败态的条件是满足 tL+t,所以我们可以对K找因子,找到最小的那个L就可以了*/#include <cstdio>int K,L;#define min(x,y) ((x)<(y)?(x):(y))int main(){ while(scanf("%d",&K)==1) { int ans = 1000000000; for( 阅读全文
posted @ 2011-06-16 13:14 AC2012 阅读(180) 评论(0) 推荐(0) 编辑
摘要: /*一个很有意思的问题。初看好像不好做。在看,可以转化是取石子问题。因为对于任意一堆数a,b。大的可能是小的好几倍,所以从a上取b可以取多个,然后才能转化为以b为大,a%b为小的下一堆。问题可以转化为:若干堆石子,最后一堆只有一个石子,现在要求从左开始取,只有前一堆取完才能取下一堆。谁取到最后一个石子算胜。可以使用必胜态必败态来做。假设石子数量是1 4 5 1从右往左推,1是必胜态,因为轮到自己的时候,可以执行一步操作就到达要求的目标。 5是必胜态,因为我可以只取4个,然后剩下一个给对方,然后就可以转到下一个必胜态。 4是必胜态,因为我可以只取3个,然后剩下的一个对对方,然后就可以转到下一个必 阅读全文
posted @ 2011-06-16 11:01 AC2012 阅读(232) 评论(0) 推荐(0) 编辑
摘要: /*NIM基础题*/#include <cstdio>int N,A[200001],ans;int main(){ while(scanf("%d",&N)==1) { if(!N) break; ans = 0; for(int i=0;i<N;i++) { scanf("%d",A+i); ans ^= A[i]; } if(ans){printf("Yes\n"); for(int i=0;i<N;i++) { if( A[i]>=(ans^A[i]) ) { printf("% 阅读全文
posted @ 2011-06-16 01:36 AC2012 阅读(283) 评论(0) 推荐(0) 编辑
摘要: /*Nim游戏,首先求出sg异或和的值。如果是胜,判断每堆石块通过变化个数能够达到败态。计数就可以了*/#include <cstdio>int N,A[1010],ans;int main(){ while(scanf("%d",&N)==1) { if(!N) break; ans = 0; for(int i=0;i<N;i++) { scanf("%d",&A[i]);ans^=A[i]; } int cnt=0; if(ans) for(int i=0;i<N;i++) { if( A[i]>= ( 阅读全文
posted @ 2011-06-16 01:22 AC2012 阅读(135) 评论(0) 推荐(0) 编辑
摘要: /*NIM游戏基础*/#include <cstdio>int N,a,ans;int main(){ while(scanf("%d",&N)==1) { ans = 0; for(int i=0;i<N;i++) { scanf("%d",&a); ans ^= a; } if(ans) printf("Yes\n"); else printf("No\n"); } return 0;} 阅读全文
posted @ 2011-06-16 00:54 AC2012 阅读(130) 评论(0) 推荐(0) 编辑