标签:
突然想到好久以前做完这份题目没写题解。蛮来写写吧。很多细节已经忘记了。。
第一题
很简单的字符串比对是否b包含a。不包含就报NO,包含就YES。。坑爹的第一次!!。把strlen放在了for循环里面。。就超时了。。超时了。。
注意:for里面的条件每次也会重新计算。
Description
Input
Output
Sample Input
sequence subsequence person compression VERDI vivaVittorioEmanueleReDiItalia caseDoesMatter CaseDoesMatter
Sample Output
Yes No Yes No
下附代码
1 #include<iostream> 2 #include<stdio.h> 3 #include<string.h> 4 #include<cmath> 5 #define INF 1000000 6 char s[100005],t[100005]; 7 int main() 8 { 9 int i=0,j=0,s_len,t_len; 10 while(scanf("%s%s",s,t)!=EOF) 11 { 12 i=0;j=0; 13 s_len=strlen(s); 14 t_len=strlen(t); 15 for(i;i<s_len&&j<t_len;) 16 if(s[i]==t[j]) 17 {i++;j++;} 18 else 19 j++; 20 if(i==strlen(s)) 21 printf("Yes\n"); 22 else 23 printf("No\n"); 24 } 25 return 0; 26 }
第二题
找规律。。其实也可以还原。但是找到规律的话也是可以做的。就是写代码的时候要认真点。思路是相邻做差,得到一个新的数组,新数组有数字,说明肯定有差括号,是1,然后这个新数组如果有一串0,说明原来的数字都是相等的,则第一位0肯定是1,但是接下来的0,就要继续往前找对应的括号,然后增加数字,具体的已经忘记了。但是就是找规律。这题1A。
Description
S (((()()())))
P-sequence 4 5 6666
W-sequence 1 1 1456
Input
Output
Sample Input
2 6 4 5 6 6 6 6 9 4 6 6 6 6 8 9 9 9
Sample Output
1 1 1 4 5 6 1 1 2 4 5 1 1 3 9
下附代码:
1 #include<iostream> 2 #include<stdio.h> 3 #include<string.h> 4 #include<cmath> 5 #include<algorithm> 6 #include<queue> 7 #define INF 1000005 8 using namespace std; 9 queue<int>q; 10 int s[1000005]={0},mark[1000005]; 11 int main() 12 { 13 int n,first,late,i,m,ans,t; 14 scanf("%d",&n); 15 while(n--) 16 { 17 for(i=0;i<30;i++) 18 {s[i]=0;mark[i]=0;} 19 scanf("%d",&m); 20 first=0; 21 for(i=0;i<m;i++) 22 { 23 scanf("%d",&late); 24 s[i]=late-first; 25 first=late; 26 } 27 for(i=0;i<m;i++) 28 { 29 if(s[i]) 30 { 31 if(i!=m-1) 32 printf("1 "); 33 else 34 printf("1\n"); 35 } 36 else 37 { 38 t=i;ans=0; 39 while(!s[t]||mark[t]==s[t]) 40 { 41 ans+=mark[t]; 42 t--; 43 } 44 while(mark[t]+1==s[t]) 45 { 46 mark[t]++; 47 ans+=s[t]; 48 t--; 49 while(!s[t]||mark[t]==s[t]) 50 { 51 ans+=mark[t]; 52 t--; 53 } 54 } 55 mark[t]++; 56 if(i!=m-1) 57 printf("%d ",ans+mark[t]+1); 58 else 59 printf("%d\n",ans+mark[t]+1); 60 } 61 } 62 } 63 return 0; 64 }
第三题
一个二叉树的前序中序序列,还原后序序列,用到了递归分治的思想,主要要分清楚两个序列的头和尾在哪里,然后可以通过找根找到中序序列中间的根,从而继续分开这两个序列。关键代码是下面这个
if(k-cc)
turn(aa+1,k-cc+aa,cc,k-1);
if(dd-k)
turn(aa+k-cc+1,bb,k+1,dd);
错了两次,算是一道考细节的递归。
下附代码:
1 #include<iostream> 2 #include<stdio.h> 3 #include<string.h> 4 #include<cmath> 5 #include<algorithm> 6 #include<queue> 7 #define INF 1000000 8 using namespace std; 9 char a[50],b[50],c[50]; 10 void turn(int aa,int bb,int cc,int dd)//n是前序m是中序 11 { 12 int k=0; 13 while(a[aa]!=b[k]) 14 { 15 k++; 16 }//找根 17 if(k-cc) 18 turn(aa+1,k-cc+aa,cc,k-1); 19 if(dd-k) 20 turn(aa+k-cc+1,bb,k+1,dd); 21 printf("%c",a[aa]); 22 } 23 int main() 24 { 25 int i,m,n,ans,t,bg,j,num,k,h=0,sum=0; 26 while(scanf("%s%s",a,b)!=EOF) 27 { 28 t=strlen(a); 29 turn(0,t-1,0,t-1); 30 for(i=1;i<=t;i++) 31 printf("%c",c[i]); 32 printf("\n"); 33 } 34 return 0; 35 }
第四题:
BFS就行。用队列来存,注意一下具体细节。
Description
Farmer John has been informed of the location of a fugitive cow and wants to catch her immediately. He starts at a point N (0 ≤ N ≤ 100,000) on a number line and the cow is at a point K (0 ≤ K ≤ 100,000) on the same number line. Farmer John has two modes of transportation: walking and teleporting.
* Walking: FJ can move from any point X to the points X - 1 or X + 1 in a single minute
* Teleporting: FJ can move from any point X to the point 2 × X in a single minute.
If the cow, unaware of its pursuit, does not move at all, how long does it take for Farmer John to retrieve it?
Input
Output
Sample Input
5 17
Sample Output
4
Hint
下附代码:
1 #include<iostream> 2 #include<stdio.h> 3 #include<string.h> 4 #include<cmath> 5 #include<algorithm> 6 #include<queue> 7 #define INF 1000000 8 using namespace std; 9 queue<int>q; 10 int vis[1000005]={0}; 11 int main() 12 { 13 int a,b,cot,ans,t,mark=0,noww; 14 scanf("%d%d",&a,&b); 15 if(a==b) 16 printf("0\n"); 17 else 18 { 19 if(a+1==b||a-1==b||a*2==b) 20 printf("1\n"); 21 else 22 { 23 q.push(a); 24 vis[a]=1; 25 while(!q.empty()) 26 { 27 ans=q.front(); 28 q.pop(); 29 if(ans-1>=0) 30 { 31 noww=ans-1; 32 if(!vis[noww]) 33 {vis[noww]=vis[ans]+1;q.push(noww);} 34 if(noww==b) 35 {printf("%d\n",vis[noww]-1);break;} 36 } 37 if(ans+1<INF) 38 { 39 noww=ans+1; 40 if(!vis[noww]) 41 {vis[noww]=vis[ans]+1;q.push(noww);} 42 if(noww==b) 43 {printf("%d\n",vis[noww]-1);break;} 44 } 45 if(ans*2<INF) 46 { 47 noww=ans*2; 48 if(!vis[noww]) 49 {vis[noww]=vis[ans]+1;q.push(noww);} 50 if(noww==b) 51 {printf("%d\n",vis[noww]-1);break;} 52 } 53 } 54 } 55 } 56 return 0; 57 }
第五题:
一道判断是不是连通的,用并查集就可以判断,但是要做一点小处理,存储的时候如果就一个数字就不管他,如果有两个或两个以上就用第一个数字当父亲,让后面其他的数字与其关联。
Description
Input
Output
Sample Input
100 4 2 1 2 5 10 13 11 12 14 2 0 1 2 99 2 200 2 1 5 5 1 2 3 4 5 1 0 0 0
Sample Output
4 1 1
下附代码:
1 #include<iostream> 2 #include<stdio.h> 3 #include<string.h> 4 #include<cmath> 5 #include<algorithm> 6 #include<queue> 7 #define INF 1000005 8 using namespace std; 9 int f[30005],mark[30005],mark1[30005]={0}; 10 int finding(int x) 11 { 12 if(x!=f[x]) 13 f[x]=finding(f[x]); 14 return f[x]; 15 } 16 int together(int x,int y) 17 { 18 int f1=finding(x); 19 int f2=finding(y); 20 if(f1!=f2) 21 {f[f2]=f1;return 1;} 22 return 0; 23 } 24 int main() 25 { 26 int i,m,n,ans,t,bg,j,num,k,h=0,cot=0,sum,late,temp; 27 while(scanf("%d%d",&n,&m)&&(n!=0||m!=0)) 28 { 29 for(i=0;i<=n;i++) 30 f[i]=i; 31 k=0; 32 while(m--) 33 { 34 scanf("%d",&num); 35 if(num>1) 36 { 37 scanf("%d",&bg); 38 if(!mark1[bg]) 39 {mark[k++]=bg;mark1[bg]=1;} 40 for(i=1;i<num;i++) 41 { 42 scanf("%d",&late); 43 together(bg,late); 44 if(!mark1[late]) 45 {mark[k++]=late;mark1[late]=1;} 46 } 47 } 48 else if(num==1) 49 {scanf("%d",&temp); 50 if(!mark1[temp]) 51 {mark[k++]=temp;mark1[temp]=1;}} 52 } 53 sum=0; 54 for(i=0;i<k;i++) 55 { 56 if(finding(0)==finding(mark[i])) 57 sum++; 58 } 59 if(sum==0) 60 printf("1\n"); 61 else 62 printf("%d\n",sum); 63 for(i=0;i<k;i++) 64 mark1[mark[i]]=0; 65 } 66 return 0; 67 }
第六题:
一道超级水的最小生成树,用kruskal就可以。但是注意储存,只需要上三角就行。之前不小心数组开小了。就超了。。
1 #include<iostream> 2 #include<stdio.h> 3 #include<string.h> 4 #include<cmath> 5 #include<algorithm> 6 #include<queue> 7 #define INF 1000000 8 using namespace std; 9 int f[100005]; 10 struct node 11 { 12 int x; 13 int y; 14 int k; 15 }c[100005]; 16 int cmp(struct node a,struct node b) 17 { 18 return a.k<b.k; 19 } 20 int finding(int x) 21 { 22 if(f[x]!=x) 23 f[x]=finding(f[x]); 24 return f[x]; 25 } 26 int together(int x,int y) 27 { 28 int f1,f2; 29 f1=finding(x); 30 f2=finding(y); 31 if(f1!=f2) 32 {f[f2]=f1;return 1;} 33 return 0; 34 } 35 int main() 36 { 37 int i,m,n,ans,t,a,b,bg,j,num,k,h=0,sum=0; 38 while(scanf("%d",&n)!=EOF) 39 { 40 h=0;ans=0;sum=0; 41 for(i=0;i<100005;i++) 42 f[i]=i; 43 for(i=1;i<=n;i++) 44 for(j=1;j<=n;j++) 45 { 46 scanf("%d",&c[h].k); 47 if(c[h].k!=0) 48 { 49 c[h].x=i;c[h].y=j; 50 h++; 51 } 52 } 53 sort(c,c+h,cmp); 54 for(i=1;i<h;i++) 55 { 56 ans=together(c[i].x,c[i].y); 57 if(ans==1) 58 { 59 sum+=c[i].k; 60 } 61 } 62 printf("%d\n",sum); 63 } 64 return 0; 65 }
第七题:
这题是最短路径,用dijkstra会超的原因居然是模板错了!!。最后只能用floyd反而过了。。无语。。模板害死人啊。
if(s[j]==false&&dis[j]<mining)
{
u=j;mining=mapp[v][j];
}
这句才是真的
Description
Input
Output
Sample Input
3 2 1 2 2 3 2 3 1 2 1 2
Sample Output
0
下附代码:
1 #include<iostream> 2 #include<stdio.h> 3 #include<string.h> 4 #include<cmath> 5 #include<algorithm> 6 #include<queue> 7 #define INF 1000000 8 using namespace std; 9 int mapp[105][105],dis[105]; 10 bool s[105]; 11 int n; 12 void dijkstra(int v) 13 { 14 int i,j; 15 for(i=1;i<=n;i++) 16 { 17 dis[i]=mapp[v][i]; 18 s[i]=false; 19 } 20 s[v]=true; 21 dis[v]=0; 22 for(i=2;i<=n;i++) 23 { 24 int mining=INF,u=v; 25 for(j=1;j<=n;j++) 26 { 27 if(s[j]==false&&dis[j]<mining) 28 { 29 u=j;mining=mapp[v][j]; 30 } 31 } 32 s[u]=true; 33 for(j=1;j<=n;j++) 34 { 35 if(s[j]==false&&mapp[u][j]<INF) 36 if(mapp[u][j]+dis[u]<dis[j]) 37 dis[j]=mapp[u][j]+dis[u]; 38 } 39 } 40 } 41 int main() 42 { 43 int i,m,ans,t,a,b,bg,j,num,k; 44 while(scanf("%d%d%d",&n,&a,&b)!=EOF) 45 {for(i=0;i<105;i++) 46 for(j=0;j<105;j++) 47 mapp[i][j]=INF; 48 for(i=1;i<=n;i++) 49 { 50 scanf("%d",&num); 51 for(j=0;j<num;j++) 52 { 53 scanf("%d",&bg); 54 if(j==0) 55 mapp[i][bg]=0; 56 else 57 mapp[i][bg]=1; 58 } 59 } 60 /*for(i=1;i<=n;i++) 61 {for(j=1;j<=n;j++) 62 printf("%d ",mapp[i][j]); 63 cout<<endl;}*/ 64 dijkstra(a); 65 /*for(j=1;j<=n;j++) 66 for(i=1;i<=n;i++) 67 for(k=1;k<=n;k++) 68 if(mapp[i][j]+mapp[j][k]<mapp[i][k]) 69 mapp[i][k]=mapp[i][j]+mapp[j][k];*/ 70 /*for(i=1;i<=n;i++) 71 printf("%d ",dis[i]); 72 cout<<endl;*/ 73 if(dis[b]==INF) 74 printf("-1\n"); 75 else 76 printf("%d\n",dis[b]); 77 /*if(mapp[a][b]==INF) 78 printf("-1\n"); 79 else 80 printf("%d\n",mapp[a][b]);*/ 81 } 82 return 0; 83 }
第八题:
这题以前做过,就是简单的素数筛一下,从小到大选择就好,注意。没有偶数。。我还调了半天。
Description
Every even number greater than 4 can be
written as the sum of two odd prime numbers.
8 = 3 + 5. Both 3 and 5 are odd prime numbers.
20 = 3 + 17 = 7 + 13.
42 = 5 + 37 = 11 + 31 = 13 + 29 = 19 + 23.
Input
Output
Sample Input
8 20 42 0
Sample Output
8 = 3 + 5 20 = 3 + 17 42 = 5 + 37
下附代码:
1 #include<iostream> 2 #include<stdio.h> 3 #include<string.h> 4 #include<cmath> 5 #include<algorithm> 6 #include<queue> 7 #define INF 1000005 8 using namespace std; 9 queue<int>q; 10 int s[1000005]={0},primee[1000005]; 11 void prime() 12 { 13 int i,k=1,cot; 14 for(i=2;i<INF;i++) 15 { 16 if(s[i]==0) 17 primee[k++]=i; 18 cot=2; 19 while(cot*i<INF) 20 { 21 s[i*cot]=1; 22 cot++; 23 } 24 } 25 } 26 int main() 27 { 28 29 int i=1,n; 30 prime(); 31 //for(i=1;i<100;i++) 32 //cout<<primee[i]<<" "; 33 while(scanf("%d",&n)&&n!=0) 34 { 35 i=1; 36 while(s[n-primee[i]]) 37 { 38 i++; 39 } 40 printf("%d = %d + %d\n",n,primee[i],n-primee[i]); 41 } 42 return 0; 43 }
第九题:
简单的进位。字符串转成数字进行加减就好。
Description
Input
Output
Sample Input
123 456 555 555 123 594 0 0
Sample Output
No carry operation. 3 carry operations. 1 carry operation.
下附代码:
1 #include<iostream> 2 #include<stdio.h> 3 #include<string.h> 4 #include<cmath> 5 char a[200005],b[200005]; 6 int main() 7 { 8 int carry,ans,t,s; 9 while(scanf("%s%s",a,b)&&(a[0]!=‘0‘||b[0]!=‘0‘)) 10 { 11 carry=0; 12 t=strlen(a)-1;s=strlen(b)-1;ans=0; 13 while(t>=0&&s>=0) 14 { 15 if((a[t]-48)+(b[s]-48)+carry>9) 16 { 17 carry=(a[t]-48)+(b[s]-48)+carry; 18 ans++; 19 carry/=10; 20 } 21 t--;s--; 22 } 23 if(t<0) 24 { 25 while(s>=0) 26 { 27 if((b[s]-48)+carry>9) 28 { 29 carry=(b[s]-48)+carry; 30 ans++;carry/=10;s--; 31 } 32 else 33 break; 34 } 35 } 36 if(s<0) 37 { 38 while(t>=0) 39 { 40 if((a[t]-48)+carry>9) 41 { 42 carry=(a[t]-48)+carry; 43 ans++;carry/=10;t--; 44 } 45 else 46 break; 47 } 48 } 49 if(ans==0) 50 printf("No carry operation.\n"); 51 else if(ans==1) 52 printf("1 carry operation.\n"); 53 else 54 printf("%d carry operations.\n",ans); 55 } 56 return 0; 57 }
第十题:
就是在n的范围内,互质的分数的个数。其实就是欧拉函数在1-n范围内求和,打个线性欧拉函数筛就搞定了。
Description
Input
Output
Sample Input
2 3 4 5 0
Sample Output
1 3 5 9
下附代码:
1 #include<iostream> 2 #include<stdio.h> 3 #include<string.h> 4 #include<cmath> 5 #include<algorithm> 6 #include<queue> 7 #define INF 1000005 8 using namespace std; 9 int target[INF],phi[INF]; 10 bool pri[INF]; 11 int main() 12 { 13 int i,m,n,ans,t,bg,j,num,k,h=0,cot=0; 14 long long int sum=0; 15 for(i=2;i<INF;i++) 16 { 17 if(pri[i]==false) 18 { 19 target[cot++]=i; 20 phi[i]=i-1; 21 } 22 for(j=0;j<cot&&i*target[j]<INF;j++) 23 { 24 pri[i*target[j]]=true; 25 if(i%target[j]==0) 26 phi[i*target[j]]=phi[i]*target[j]; 27 else 28 phi[i*target[j]]=phi[i]*(target[j]-1); 29 } 30 } 31 while(scanf("%d",&n)&&n!=0) 32 { 33 sum=0; 34 for(i=2;i<=n;i++) 35 sum+=phi[i]; 36 printf("%lld\n",sum); 37 } 38 return 0; 39 }
其实还有两题。但都是比较困难的题目了。。待以后有余力的话继续补充。
又结束了一次训练,感觉还是没什么长进,希望暑假能提高代码能力。。加油!
标签:
原文地址:http://www.cnblogs.com/linminxuan/p/4559642.html