Codeforces Round #427 (Div. 2)
还差7分就蓝名了,加油!!!!
A. Key races
题目大意:有两个打字员,一共有s个字要打,第一个打字员打字速度为v1秒/字 ,延迟为t1,第二个打字员
打字速度为v2秒/字,延迟为t2。开始打字前和开始打字后都有一个延迟,问你谁快。
思路:水题,XJB搞搞就好。
#include<bits/stdc++.h> using namespace std; int s,v1,v2,t1,t2; int main() { cin>>s>>v1>>v2>>t1>>t2; int x=v1*s+2*t1; int y=v2*s+2*t2; //cout<<x<<endl; //cout<<y<<endl; if(x>y) puts("Second"); else if(x<y) puts("First"); else puts("Friendship"); return 0; }
B. The number on the board
题目大意:给你一串数字,要求每个数字相加要大于等于k,问你最少改变几个数字。
思路:先排序,如果不够优先用小的补。
#include<bits/stdc++.h> using namespace std; char s[100005]; int k; int sum[100005]; int main() { cin>>k; scanf("%s",s+1); int len=strlen(s+1); sort(s+1,s+len+1); int cnt=0; for(int i=1;i<=len;i++) { sum[i]=sum[i-1]+(s[i]-'0'); cnt+=s[i]-'0'; } if(cnt>=k) { puts("0"); return 0; } int ans=0; for(int i=1;i<=len;i++) { ans++; if(cnt+9*i-sum[i]>=k) break; } cout<<ans<<endl; return 0; }
C. Star sky
题目大意:在100*100的网格中,中n个星星,每个星星的初始亮度为s[ i ],且所有星星的最大亮度为c(c<=10),每过一秒
所有星星亮度加1,亮度为c的变成0。有q个询问,每个询问给你一个矩形,问在 t 秒的时候这里面所有星星的亮度总和为多少。
思路:考虑到c<=10比较小,我们可以开一个dp[ 101 ][ 101 ][ 11 ], dp[ i ][ j ][ k ] 表示以( i , j )为右上顶点,( 0 , 0)为左下顶点
的矩形中亮度为k的星星有多少个。 这样在询问中我们就能O(1)进行查询了。
#include<bits/stdc++.h> using namespace std; int n,q,c,mp[105][105][11],dp[105][105][11]; int main() { scanf("%d%d%d",&n,&q,&c); for(int i=1;i<=n;i++) { int x,y,s; scanf("%d%d%d",&x,&y,&s); mp[x][y][s]++; } for(int i=1;i<=100;i++) { for(int j=1;j<=100;j++) { for(int k=0;k<=10;k++) { dp[i][j][k]=mp[i][j][k]; if(i==1 && j==1) continue; if(j==1) dp[i][j][k]+=dp[i-1][j][k]; else if(i==1) dp[i][j][k]+=dp[i][j-1][k]; else { dp[i][j][k]+=dp[i-1][j][k]+dp[i][j-1][k]; dp[i][j][k]-=dp[i-1][j-1][k]; } } } } while(q--) { int sum=0; int x1,y1,x2,y2,t; scanf("%d%d%d%d%d",&t,&x1,&y1,&x2,&y2); for(int i=0;i<=10;i++) { int cnt=0; cnt=dp[x2][y2][i]+dp[x1-1][y1-1][i]-dp[x1-1][y2][i]-dp[x2][y1-1][i]; sum+=cnt*((i+t)%(c+1)); } printf("%d\n",sum); } return 0; }
D. Palindromic characteristics
题目大意:给你一个字符串,让你找各个k-回文串的数量,定义:1-回文串为普通回文串,k-回文串为 这个回文串的前一部分和
后一部分都为(k-1)-回文串。
思路:其实只要会dp求回文串的数量这个就好写了,然后我比赛的时候忘了怎么用dp求回文串就GG了,复杂度O( n ^ 2 ),好像
还有更简单的O( n * logn )的方法。
#include<bits/stdc++.h> using namespace std; int ans[5005],dp[5005][5005]; char s[5005]; int main() { scanf("%s",s); int len=strlen(s); for(int i=0;i<len;i++) { dp[i][i]=1; if(i!=len-1 && s[i]==s[i+1]) { dp[i][i+1]=2; ans[2]++; } } ans[1]+=len; for(int k=3;k<=len;k++) { for(int i=0;i+k-1<len;i++) { int j=i+k-1; if(s[i]==s[j] && dp[i+1][j-1]) { int m=(i+j)>>1; if((i+j)%2) { dp[i][j]=min(dp[i][m],dp[m+1][j])+1; ans[dp[i][j]]++; } else { dp[i][j]=min(dp[i][m-1],dp[m+1][j])+1; ans[dp[i][j]]++; } } } } for(int i=len-1;i>=1;i--) ans[i]+=ans[i+1]; for(int i=1;i<=len;i++) printf("%d%c",ans[i],i==len?'\n':' '); return 0; }
ps:
顺便贴一手 o(n) 求字符串的最长回文子串的manacher算法
//manacher算法 #include<bits/stdc++.h> using namespace std; char ss[5005],s[10005]; int p[5005]; int main() { while(scanf("%s",ss)!=EOF) { int len=strlen(ss); s[0]='$'; s[1]='#'; int cnt=2; for(int i=0;i<len;i++) { s[cnt++]=ss[i]; s[cnt++]='#'; } s[cnt]=0; int id=0,ml=0; for(int i=1;i<cnt;i++) { if(i<p[id]+id) p[i]=min(p[2*id-i],p[id]+id-i);//如果i在已知的范围内 else p[i]=1; while(s[i+p[i]]==s[i-p[i]]) p[i]++;//以i为中心扩充 if(id+p[id]<i+p[i]) id=i; if(ml<p[i]) ml=p[i]; } cout<<ml-1<<endl; } return 0; }