1001、Post Robot
字符串匹配题题,子串长度不超过6,所以直接暴力。
(读一一行带空格的字符串,可以使用while(gets());)
1 //============================================================================ 2 // Name : 20140920.cpp 3 // Author : 4 // Version : 5 // Copyright : Your copyright notice 6 // Description : Hello World in C++, Ansi-style 7 //============================================================================ 8 9 #include <iostream> 10 #include <iostream> 11 #include <stdio.h> 12 #include <math.h> 13 #include <string.h> 14 #include <vector> 15 #include <algorithm> 16 using namespace std; 17 #define LL __int64 18 char f[10010]; 19 int main() { 20 freopen("in.txt", "r", stdin); 21 //freopen("out.txt","w",stdout); 22 while(gets(f)){ 23 int len =strlen(f); 24 for(int i=0;i<len;i++){ 25 if(f[i]=='A' && f[i+1]=='p' && f[i+2]=='p' && f[i+3]=='l' && f[i+4]=='e'){ 26 puts("MAI MAI MAI!"); 27 } 28 else if(f[i]=='i' && f[i+1]=='P' && f[i+2]=='a' && f[i+3]=='d'){ 29 puts("MAI MAI MAI!"); 30 } 31 else if(f[i]=='i' && f[i+1]=='P' && f[i+2]=='h' && f[i+3]=='o' && f[i+4]=='n' && f[i+5]=='e'){ 32 puts("MAI MAI MAI!"); 33 } 34 else if(f[i]=='i' && f[i+1]=='P' && f[i+2]=='o' && f[i+3]=='d' ){ 35 puts("MAI MAI MAI!"); 36 } 37 else if(f[i]=='S' && f[i+1]=='o' && f[i+2]=='n' && f[i+3]=='y' ) 38 puts("SONY DAFA IS GOOD!"); 39 } 40 } 41 42 return 0; 43 }
1002、Boring String Problem
后缀数组+RMQ+二分
后缀数组二分确定第K不同子串的位置 , 二分LCP确定可选的区间范围 , RMQ求范围内最小的sa
清华AC代码:(的确高大上,先贴着,参考学习)
1 #include <algorithm> 2 #include <cstring> 3 #include <cstdlib> 4 #include <cstdio> 5 #define N 200010 6 #define int64 long long 7 #define For(i,x,y) for (i=x;i<=y;i++) 8 using namespace std; 9 struct ww { 10 int a,b; 11 } f[N][20]; 12 int i,j,k,n,m,an,re; 13 int r[N],rr[N],sa[N],t[N],tt[N],h[N],len[N]; 14 char p[N]; 15 int64 preh[N]; 16 inline void Sa() { 17 int i,j,k=30; 18 For(i,1,n) r[i]=p[i]-'a'+1; 19 For(i,n+1,N-1) r[i]=0; 20 for (i=1;i<=n;i<<=1) { 21 For(j,1,k) t[j]=0; 22 For(j,1,n) t[r[j+i]]++; 23 For(j,1,k) t[j]+=t[j-1]; 24 for (j=n;j;j--) tt[t[r[j+i]]--]=j; 25 For(j,1,k) t[j]=0; 26 For(j,1,n) t[r[j]]++; 27 For(j,1,k) t[j]+=t[j-1]; 28 for (j=n;j;j--) sa[t[r[tt[j]]]--]=tt[j]; 29 rr[sa[1]]=k=1; 30 For(j,2,n) if (r[sa[j]]==r[sa[j-1]]&&r[sa[j]+i]==r[sa[j-1]+i]) 31 rr[sa[j]]=rr[sa[j-1]]; else rr[sa[j]]=++k; 32 For(j,1,n) r[j]=rr[j]; 33 if (k==n) return; 34 } 35 } 36 inline void Getheight() { 37 int i,j,k=0; 38 for (i=1;i<=n;h[r[i++]]=k) 39 for (k?k--:0,j=sa[r[i]-1];p[j+k]==p[i+k];k++); 40 } 41 inline void pre() { 42 int i,j; 43 For(i,1,n) f[i][0]=(ww){h[i],sa[i]}; 44 For(j,1,19)For(i,1,n-(1<<j)+1) { 45 int A=i+(1<<j-1); 46 f[i][j].a=min(f[i][j-1].a,f[A][j-1].a); 47 f[i][j].b=min(f[i][j-1].b,f[A][j-1].b); 48 } 49 } 50 inline int get(int x,int y) { 51 int i,an=N; 52 for (i=19;i>=0;i--) if (f[x][i].a>=y) an=min(an,f[x][i].b),x+=1<<i; 53 return an; 54 } 55 int main() { 56 //freopen("1002.in","r",stdin); 57 //freopen("1002.out","w",stdout); 58 for (;scanf("%s",p+1)!=EOF;) { 59 n=strlen(p+1); 60 Sa(); Getheight(); 61 For(i,1,n) len[i]=n-sa[i]+1; 62 For(i,1,n) preh[i]=preh[i-1]+len[i]-min(len[i],h[i]); 63 an=re=0; 64 scanf("%d",&m); 65 pre(); 66 For(i,1,m) { 67 int64 x; 68 scanf("%I64d",&x); 69 x=(x^an^re)+1; 70 if (x>preh[n]) an=re=0; 71 else { 72 int l=1,r=n,mid; 73 for (;l<=r;) { 74 mid=(l+r)/2; 75 if (preh[mid]<x) l=mid+1; 76 else r=mid-1; 77 } 78 x-=preh[l-1]; 79 an=min(sa[l],get(l+1,h[l]+x)); 80 re=an+h[l]+x-1; 81 } 82 printf("%d %d\n",an,re); 83 } 84 } 85 return 0; 86 }
1003、
DP
1005、
博弈,不会。
1006、Dice
·简单的bfs、这题重点在于每次正方体旋转之后的状态描述,状态保存;找到四种翻转之后的状态描述方式之后即可。
·bfs重点:
记忆话搜索! int vis[] ; //这里使用hash()函数的时候,可以使用一维变量,否则状态如何表示,记忆话的方式也如何表示。
(这点很重要,不然很有可能会超时!)
hash值代表状态,构造哈希函数。 int hash(int a[]){ return .. ;}
队列的使用 #include <queue>
每种状态的区分描述: if ... else if ... else if... 等 。 每一次进队的状态数量
广搜题目,有时可以限制深度。(这道题:一共6!中情况)
经典bfs代码:(600+ms,方法比较慢)
1 #include <iostream> 2 #include <stdio.h> 3 #include <stdlib.h> 4 #include <string.h> 5 #include <queue> 6 using namespace std; 7 8 int start[10],end[10]; 9 int vis[10][10][10][10][10][10]; 10 struct LNode{ 11 int f[7],ans; //描述状态以及当前深度。 12 }t,m,f; 13 14 int deal(){ 15 for(int i=1;i<=6;i++) 16 if(t.f[i]==end[i]) continue; 17 else return 0; 18 return 1; 19 } 20 int bfs(){ 21 queue<LNode> q; 22 for(int i=1;i<=6;i++) t.f[i] = start[i]; t.ans = 0; 23 q.push(t); 24 vis[t.f[1]][t.f[2]][t.f[3]][t.f[4]][t.f[5]][t.f[6]]=1; //进行标记 25 while(!q.empty()){ 26 t = q.front(); 27 q.pop(); 28 29 //判断是否满足条件 30 if(deal()) return t.ans; 31 for(int i=1;i<=4;i++){ 32 if(i==1) 33 { 34 f.f[1]=t.f[4]; 35 f.f[2]=t.f[3]; 36 f.f[3]=t.f[1]; 37 f.f[4]=t.f[2]; 38 f.f[5]=t.f[5]; 39 f.f[6]=t.f[6]; 40 if(vis[f.f[1]][f.f[2]][f.f[3]][f.f[4]][f.f[5]][f.f[6]]==0) 41 { 42 f.ans=t.ans+1; 43 vis[f.f[1]][f.f[2]][f.f[3]][f.f[4]][f.f[5]][f.f[6]]=1; //进行标记! 44 q.push(f); 45 } 46 } 47 else if(i==2) 48 { 49 f.f[1]=t.f[3]; 50 f.f[2]=t.f[4]; 51 f.f[3]=t.f[2]; 52 f.f[4]=t.f[1]; 53 f.f[5]=t.f[5]; 54 f.f[6]=t.f[6]; 55 if(vis[f.f[1]][f.f[2]][f.f[3]][f.f[4]][f.f[5]][f.f[6]]==0) 56 { 57 f.ans=t.ans+1; 58 vis[f.f[1]][f.f[2]][f.f[3]][f.f[4]][f.f[5]][f.f[6]]=1; 59 q.push(f); 60 } 61 } 62 else if(i==3) 63 { 64 f.f[1]=t.f[6]; 65 f.f[2]=t.f[5]; 66 f.f[3]=t.f[3]; 67 f.f[4]=t.f[4]; 68 f.f[5]=t.f[1]; 69 f.f[6]=t.f[2]; 70 if(vis[f.f[1]][f.f[2]][f.f[3]][f.f[4]][f.f[5]][f.f[6]]==0) 71 { 72 f.ans=t.ans+1; 73 vis[f.f[1]][f.f[2]][f.f[3]][f.f[4]][f.f[5]][f.f[6]]=1; 74 q.push(f); 75 } 76 } 77 else if(i==4) 78 { 79 f.f[1]=t.f[5]; 80 f.f[2]=t.f[6]; 81 f.f[3]=t.f[3]; 82 f.f[4]=t.f[4]; 83 f.f[5]=t.f[2]; 84 f.f[6]=t.f[1]; 85 if(vis[f.f[1]][f.f[2]][f.f[3]][f.f[4]][f.f[5]][f.f[6]]==0) 86 { 87 f.ans=t.ans+1; 88 vis[f.f[1]][f.f[2]][f.f[3]][f.f[4]][f.f[5]][f.f[6]]=1; 89 q.push(f); 90 } 91 } 92 } 93 } 94 return -1; 95 } 96 int main(){ 97 //freopen("in.txt","r",stdin); 98 while(scanf("%d%d%d%d%d%d",&start[1],&start[2],&start[3],&start[4],&start[5],&start[6])!=EOF){ 99 for(int i=1;i<7;i++) scanf("%d",&end[i]); 100 memset(vis,0,sizeof(vis)); 101 printf("%d\n",bfs()); 102 } 103 return 0; 104 }
hash函数表示状态代码:(摘自网络)
1 #include <cstdlib> 2 #include <climits> 3 #include <cassert> 4 #include <cstdio> 5 #include <cmath> 6 #include <ctime> 7 #include <functional> 8 #include <algorithm> 9 #include <memory.h> 10 #include <numeric> 11 #include <utility> 12 #include <iomanip> 13 #include <iostream> 14 #include <sstream> 15 #include <fstream> 16 #include <cstring> 17 #include <vector> 18 #include <bitset> 19 #include <deque> 20 #include <queue> 21 #include <stack> 22 #include <list> 23 #include <set> 24 #include <map> 25 26 #define MX 1000000 27 using namespace std; 28 29 int rot[4][10] = {{2, 1, 3, 0, 2}, {3, 1, 2, 0, 3}, {4, 1, 5, 0, 4}, {5, 1, 4, 0, 5}}; 30 31 int que[MX]; 32 int chk[MX], T; 33 34 int hash(int a[]) { 35 36 int i, v = 1, s = 0; 37 for (i = 0; i < 6; i ++) { 38 s += a[i] * v; 39 v *= 7; 40 } 41 return s; 42 } 43 44 void get(int a[], int u) { 45 46 int i; 47 for (i = 0; i <= 5; i ++) { 48 a[i] = u % 7; 49 u /= 7; 50 } 51 } 52 53 int main() { 54 55 // freopen("in.txt", "r", stdin); 56 // freopen("out.txt", "w", stdout); 57 58 int i, k, S, E, u, dp; 59 int a[10], b[10], c[10], d[10], e[10]; 60 while (scanf("%d", &a[0]) == 1) { 61 62 for (i = 1; i < 6; i ++) scanf("%d", a + i); 63 for (i = 0; i < 6; i ++) scanf("%d", b + i); 64 65 66 T ++; 67 S = hash(a); 68 E = hash(b); 69 chk[S] = T; 70 71 int bf = 0; 72 int st = 0, en = 0; 73 que[en ++] = S; que[en ++] = 0; 74 while (st < en) { 75 76 u = que[st ++]; dp = que[st ++]; 77 78 if (u == E) { 79 printf("%d\n", dp); 80 bf = 1; 81 break; 82 } 83 get(c, u); 84 for (i = 0; i < 4; i ++) { 85 if (i < 2) { 86 d[4] = c[4], d[5] = c[5]; 87 for (k = 1; k <= 4; k ++) d[rot[i][k]] = c[rot[i][k - 1]]; 88 } else { 89 d[2] = c[2], d[3] = c[3]; 90 for (k = 1; k <= 4; k ++) d[rot[i][k]] = c[rot[i][k - 1]]; 91 } 92 int v = hash(d); 93 if (chk[v] == T) continue; 94 chk[v] = T; 95 que[en ++] = v; que[en ++] = dp + 1; 96 } 97 } 98 if (!bf) printf("-1\n"); 99 } 100 return 0; 101 }
1008、Number Sequence
寻找题意特殊点:
我们会发现不论如何,最终的最大值都为(1+n)*n.
从另外一方面想,题目又与二进制有关,我们会发现,对于不超过2^k-1的数字,总能找到一个数字与其异或,结果为2^k-1.以此为线索进行贪心。
(这里注意贪心顺序,需要从大到小进行)
---注意一般10^5左右的复杂度都需要进行一次排序。
1 //============================================================================ 2 // Name : 20140920.cpp 3 // Author : 4 // Version : 5 // Copyright : Your copyright notice 6 // Description : Hello World in C++, Ansi-style 7 //============================================================================ 8 9 #include <iostream> 10 #include <iostream> 11 #include <stdio.h> 12 #include <math.h> 13 #include <string.h> 14 #include <vector> 15 #include <algorithm> 16 using namespace std; 17 #define LL __int64 18 int f[100010],f1[100010]; 19 int s[25] = {0}; 20 21 void init(){ 22 int m = 2; 23 for(int i=0;i<25;i++){ 24 s[i] = m-1; 25 m *= 2; 26 } 27 } 28 int Do(int n){ 29 for(int i=0;i<25;i++) if(n==s[i]) return 1; 30 return 0; 31 } 32 int search(int x){ 33 int i; 34 for(i=0;i<25;i++){ 35 if(x > s[i]) continue; 36 else break; 37 } 38 return s[i]; 39 } 40 int deal(int i){ 41 int t = search(i); 42 int m = t - i; 43 f1[i] = m; 44 f1[m] = i; 45 } 46 int main() { 47 //freopen("in.txt", "r", stdin); 48 //freopen("out.txt","w",stdout); 49 int n;init(); 50 while(scanf("%d",&n)!=EOF){ 51 for(int i=0;i<=n;i++) { 52 scanf("%d",&f[i]); 53 } 54 printf("%I64d\n",(__int64)(n+1)*(n)); 55 for(int i=0;i<=n;i++) f1[i] = -1; 56 int flag=1; 57 if(Do(n)) flag=0; //flag = 1 时,0与n匹配,正常进行即可; 否则 58 else f1[0] = 0; 59 for(int i=n;i>=flag;i--){ 60 if(f1[i]== -1) deal(i); 61 } 62 for(int i=0;i<=n;i++){ 63 if(i) printf(" "); 64 printf("%d",f1[f[i]]); 65 } 66 printf("\n"); 67 } 68 return 0; 69 }
1009、233 Matrix
技巧:矩阵快速幂、
对于题目中有明显表示说的二维数据,如果两维相差比较大,一般会使用到矩阵快速幂
·10*10的矩阵,进行10^9次方单位的快速幂运算,大约3s。
1 //============================================================================ 2 // Name : 20140920.cpp 3 // Author : 4 // Version : 5 // Copyright : Your copyright notice 6 // Description : Hello World in C++, Ansi-style 7 //============================================================================ 8 9 #include <iostream> 10 #include <iostream> 11 #include <stdio.h> 12 #include <math.h> 13 #include <string.h> 14 #include <vector> 15 #include <algorithm> 16 using namespace std; 17 #define Mod 10000007 18 #define SMod Mod 19 #define lll __int64 20 #define LL __int64 21 22 int n,m; 23 lll a[100006],sum[100005]; 24 25 struct Matrix 26 { 27 lll m[13][13]; 28 Matrix() 29 { 30 memset(m,0,sizeof(m)); 31 for(int i=1;i<=n+2;i++) 32 m[i][i] = 1LL; 33 } 34 }; 35 36 Matrix Mul(Matrix a,Matrix b) 37 { 38 Matrix res; 39 int i,j,k; 40 for(i=1;i<=n+2;i++) 41 { 42 for(j=1;j<=n+2;j++) 43 { 44 res.m[i][j] = 0; 45 for(k=1;k<=n+2;k++) 46 res.m[i][j] = (res.m[i][j]+(a.m[i][k]*b.m[k][j])%SMod + SMod)%SMod; 47 } 48 } 49 return res; 50 } 51 52 Matrix fastm(Matrix a,int b) //返回a^b次方 53 { 54 Matrix res; 55 while(b) 56 { 57 if(b&1) 58 res = Mul(res,a); 59 a = Mul(a,a); 60 b >>= 1; 61 } 62 return res; 63 } 64 65 int main() 66 { 67 freopen("in.txt", "r", stdin); 68 //freopen("out.txt","w",stdout); 69 int i,j; 70 while(scanf("%d%d",&n,&m)!=EOF) 71 { 72 sum[0] = 0; 73 for(i=1;i<=n;i++) 74 { 75 scanf("%I64d",&a[i]); //第一列的数字 76 sum[i] = (sum[i-1] + a[i]); 77 } 78 lll suma = sum[n]; 79 if(m == 1) 80 { 81 printf("%I64d\n",(233LL+suma)%Mod); 82 continue; 83 } 84 85 Matrix base; 86 memset(base.m,0,sizeof(base.m)); 87 for(i=1;i<=n+1;i++) // 这里n最大为10, m开到了[13][13],(0位置没有用) 88 base.m[i][1] = 10LL; 89 for(i=2;i<=n+1;i++) 90 { 91 for(j=2;j<=n+1;j++) 92 { 93 if(i >= j) 94 base.m[i][j] = 1LL; 95 } 96 } 97 for(i=1;i<=n+2;i++) 98 base.m[i][n+2] = 1LL; 99 //初始化需要进行快速幂的矩阵! 100 101 Matrix Right; 102 memset(Right.m,0,sizeof(Right.m)); 103 Right.m[1][1] = 233LL; 104 for(i=2;i<=n+1;i++) 105 Right.m[i][1] = (233LL+sum[i-1])%Mod; //构造第一列的数据,之后后面进行m-1次的矩阵快速幂 106 Right.m[n+2][1] = 3LL; 107 108 Matrix ans = fastm(base,m-1); 109 ans = Mul(ans,Right); 110 printf("%I64d\n",ans.m[n+1][1]%Mod); 111 } 112 return 0; 113 }
·注意矩阵构造的方法,这点是难点。