华中农业大学第五届程序设计大赛网络同步赛解题报告2(转)
Posted gongpixin
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了华中农业大学第五届程序设计大赛网络同步赛解题报告2(转)相关的知识,希望对你有一定的参考价值。
今天实在累了,还有的题晚点补。。。。
题目链接:http://acm.hzau.edu.cn/problemset.php?page=3
题目:acm.hzau.edu.cn/5th.pdf
A:Little Red Riding Hood
题意:给你n朵花,每朵花有个权值,然后每次取花最少要间隔k朵,求权值最大;
思路:简单dp;
1 #pragma comment(linker, "/STACK:1024000000,1024000000") 2 #include<iostream> 3 #include<cstdio> 4 #include<cmath> 5 #include<string> 6 #include<queue> 7 #include<algorithm> 8 #include<stack> 9 #include<cstring> 10 #include<vector> 11 #include<list> 12 #include<set> 13 #include<map> 14 using namespace std; 15 #define ll long long 16 #define pi (4*atan(1.0)) 17 #define eps 1e-4 18 #define bug(x) cout<<"bug"<<x<<endl; 19 const int N=1e6+10,M=1e6+10,inf=2147483647; 20 const ll INF=1e18+10,mod=2147493647; 21 ///数组大小 22 int a[N]; 23 ll dp[N]; 24 int main() 25 { 26 int n,k; 27 int T; 28 scanf("%d",&T); 29 while(T--) 30 { 31 memset(dp,0,sizeof(dp)); 32 scanf("%d%d",&n,&k); 33 for(int i=1;i<=n;i++) 34 scanf("%d",&a[i]); 35 for(int i=1;i<=n;i++) 36 if(i<=k)dp[i]=max(dp[i-1],1LL*a[i]); 37 else dp[i]=max(dp[i-1],dp[i-k-1]+a[i]); 38 printf("%lld\\n",dp[n]); 39 } 40 return 0; 41 }
D:gcd
1 #pragma comment(linker, "/STACK:1024000000,1024000000") 2 #include<iostream> 3 #include<cstdio> 4 #include<cmath> 5 #include<string> 6 #include<queue> 7 #include<algorithm> 8 #include<stack> 9 #include<cstring> 10 #include<vector> 11 #include<list> 12 #include<set> 13 #include<map> 14 using namespace std; 15 #define ll long long 16 #define pi (4*atan(1.0)) 17 #define eps 1e-4 18 #define bug(x) cout<<"bug"<<x<<endl; 19 const int N=1e6+10,M=1e6+10,inf=2147483647; 20 const ll INF=1e18+10,mod=2147493647; 21 22 ///数组大小 23 ll MOD; 24 struct Matrix 25 { 26 ll a[2][2]; 27 Matrix() 28 { 29 memset(a,0,sizeof(a)); 30 } 31 void init() 32 { 33 for(int i=0;i<2;i++) 34 for(int j=0;j<2;j++) 35 a[i][j]=(i==j); 36 } 37 Matrix operator + (const Matrix &B)const 38 { 39 Matrix C; 40 for(int i=0;i<2;i++) 41 for(int j=0;j<2;j++) 42 C.a[i][j]=(a[i][j]+B.a[i][j])%MOD; 43 return C; 44 } 45 Matrix operator * (const Matrix &B)const 46 { 47 Matrix C; 48 for(int i=0;i<2;i++) 49 for(int k=0;k<2;k++) 50 for(int j=0;j<2;j++) 51 C.a[i][j]=(C.a[i][j]+1LL*a[i][k]*B.a[k][j])%MOD; 52 return C; 53 } 54 Matrix operator ^ (const ll &t)const 55 { 56 Matrix A=(*this),res; 57 res.init(); 58 ll p=t; 59 while(p) 60 { 61 if(p&1)res=res*A; 62 A=A*A; 63 p>>=1; 64 } 65 return res; 66 } 67 }; 68 int main() 69 { 70 Matrix base; 71 base.a[0][0]=1;base.a[0][1]=1; 72 base.a[1][0]=1;base.a[1][1]=0; 73 int T; 74 scanf("%d",&T); 75 while(T--) 76 { 77 int n,m,p; 78 scanf("%d%d%d",&n,&m,&p); 79 int x=__gcd(n+2,m+2); 80 MOD=p; 81 if(x<=2) 82 printf("%d\\n",1%p); 83 else 84 { 85 Matrix ans=base^(x-2); 86 printf("%lld\\n",(ans.a[0][0]+ans.a[0][1])%MOD); 87 } 88 } 89 return 0; 90 }
E:One Stroke
题意:给你一棵二叉树,点有点权,每次往左或者往右走,求最长走的路,并且点权和小于k;
思路:官方题解,尺取,我的写法,树上二分,
对于一条链,枚举每个点为终点,vector存该点到根节点的前缀和,二分一下即可;
详见代码;
1 #pragma comment(linker, "/STACK:1024000000,1024000000") 2 #include<iostream> 3 #include<cstdio> 4 #include<cmath> 5 #include<string> 6 #include<queue> 7 #include<algorithm> 8 #include<stack> 9 #include<cstring> 10 #include<vector> 11 #include<list> 12 #include<set> 13 #include<map> 14 using namespace std; 15 #define ll long long 16 #define pi (4*atan(1.0)) 17 #define eps 1e-4 18 #define bug(x) cout<<"bug"<<x<<endl; 19 const int N=1e6+10,M=1e6+10,inf=2147483647; 20 const ll INF=1e18+10,mod=2147493647; 21 22 ///数组大小 23 int n,ans,k,a[N]; 24 vector<int>v; 25 void dfs(int x) 26 { 27 int s=0,t=v.size()-1; 28 int e=v.size()-1,ansq=-1; 29 while(s<=e) 30 { 31 int mid=(s+e)>>1; 32 if(v[t]-v[mid]<=k) 33 { 34 ansq=mid; 35 e=mid-1; 36 } 37 else s=mid+1; 38 } 39 if(v[t]<=k)ans=max(ans,t+1); 40 else ans=max(ans,t-ansq); 41 int z=v[v.size()-1]; 42 if(x*2<=n) 43 { 44 v.push_back(z+a[x<<1]); 45 dfs(x<<1); 46 v.pop_back(); 47 } 48 if(x*2+1<=n) 49 { 50 v.push_back(z+a[x<<1|1]); 51 dfs(x<<1|1); 52 v.pop_back(); 53 } 54 } 55 int main() 56 { 57 int T; 58 scanf("%d",&T); 59 while(T--) 60 { 61 ans=0; 62 v.clear(); 63 scanf("%d%d",&n,&k); 64 for(int i=1;i<=n;i++) 65 scanf("%d",&a[i]); 66 v.push_back(a[1]); 67 dfs(1); 68 if(ans)printf("%d\\n",ans); 69 else printf("-1\\n"); 70 } 71 return 0; 72 }
G:Sequence Number
题意:找出最远的i<=j&&a[i]<=a[j]的长度;
思路:这是一道排序可以过的题,也可以rmq+二分 最快的写法可以用单调栈做到O(n)
我是求后面的最大值后缀,二分后缀;
1 #pragma comment(linker, "/STACK:1024000000,1024000000") 2 #include<iostream> 3 #include<cstdio> 4 #include<cmath> 5 #include<string> 6 #include<queue> 7 #include<algorithm> 8 #include<stack> 9 #include<cstring> 10 #include<vector> 11 #include<list> 12 #include<set> 13 #include<map> 14 using namespace std; 15 #define ll long long 16 #define pi (4*atan(1.0)) 17 #define eps 1e-4 18 #define bug(x) cout<<"bug"<<x<<endl; 19 const int N=1e5+10,M=1e6+10,inf=2147483647; 20 const ll INF=1e18+10,mod=2147493647; 21 22 int a[N],nex[N]; 23 int main() 24 { 25 int n; 26 while(~scanf("%d",&n)) 27 { 28 memset(nex,0,sizeof(nex)); 29 for(int i=1;i<=n;i++) 30 scanf("%d",&a[i]); 31 for(int j=n;j>=1;j--) 32 nex[j]=max(a[j],nex[j+1]); 33 int ans=0; 34 for(int i=1;i<=n;i++) 35 { 36 int s=i,e=n,pos=-1; 37 while(s<=e) 38 { 39 int mid=(s+e)>>1; 40 if(nex[mid]>=a[i]) 41 pos=mid,s=mid+1; 42 else e=mid-1; 43 } 44 ans=max(ans,pos-i); 45 } 46 printf("%d\\n",ans); 47 } 48 return 0; 49 }
J:Color Circle
题意:对于一个点,找长度大于4,相同字母,并且回到原点;
思路:暴力搜索;
1 #pragma comment(linker, "/STACK:1024000000,1024000000") 2 #include<iostream> 3 #include<cstdio> 4 #include<cmath> 5 #include<string> 6 #include<queue> 7 #include<algorithm> 8 #include<stack> 9 #include<cstring> 10 #include<vector> 11 #include<list> 12 #include<set> 13 #include<map> 14 using namespace std; 15 #define ll long long 16 #define pi (4*atan(1.0)) 17 #define eps 1e-4 18 #define bug(x) cout<<"bug"<<x<<endl; 19 const int N=1e2+10,M=1e6+10,inf=2147483647; 20 const ll INF=1e18+10,mod=2147493647; 21 22 ///数组大小 23 24 char a[N][N],vis[N][N]; 25 int n,m,ans; 26 int xx[4]={0,1,0,-1}; 27 int yy[4]={1,0,-1,0}; 28 int check(int x,int y) 29 { 30 if(x<=0||x>n||y<=0||y>m) 31 return 0; 32 return 1; 33 } 34 void dfs(int x,int y,int dep) 35 { 36 if(ans)return; 37 for(int i=0;i<4;i++) 38 { 39 int xxx=x+xx[i]; 40 int yyy=y+yy[i]; 41 if(check(xxx,yyy)&&a[xxx][yyy]==a[x][y]) 42 { 43 if(vis[xxx][yyy]&&dep-vis[xxx][yyy]+1>=4) 44 { 45 ans=1; 46 } 47 else if(!vis[xxx][yyy]) 48 { 49 vis[xxx][yyy]=dep; 50 dfs(xxx,yyy,dep+1); 51 vis[xxx][yyy]=0; 52 } 53 } 54 } 55 } 56 int main() 57 { 58 while(~scanf("%d%d",&n,&m)) 59 { 60 memset(vis,0,sizeof(vis)); 61 ans=0; 62 for(int i=1;i<=n;i++) 63 scanf("%s",a[i]+1); 64 for(int i=1;i<=n;i++) 65 { 66 for(int j=1;j<=m;j++) 67 { 68 dfs(i,j,1); 69 if(ans)break; 70 } 71 if(ans)break; 72 } 73 if(ans)printf("Yes\\n"); 74 else printf("No\\n"); 75 } 76 return 0; 77 }
K:Deadline
题意:给你n个bug,每个bug最晚修复时间,一个程序猿需要一天修复一个bug,问需要多少个程序猿才能修复成功;
思路:开始sort一下,遍历过去超时;
后面想想发现>=n的数根本没有必要,一个程序员总是够的,所以遍历,标记小于n的就是;
这题只要想到思路还是很简单的,假设所有工程师每天都在修复bug,那么对天数记录bug的前缀和,O(n)得到答案max(pre[i]+i-1)/i)
1 #pragma comment(linker, "/STACK:1024000000,1024000000") 2 #include<iostream> 3 #include<cstdio> 4 #include<cmath> 5 #include<string> 6 #include<queue> 7 #include<algorithm> 8 #include<stack> 9 #include<cstring> 10 #include<vector> 11 #include<list> 12 #include<set> 13 #include<map> 14 using namespace std; 15 #define ll long long 16 #define pi (4*atan(1.0)) 17 #define eps 1e-4 18 #define bug(x) cout<<"bug"<<x<<endl; 19 const int N=1e6+10,M=1e6+10,inf=2147483647; 20 const ll INF=1e18+10,mod=2147493647; 21 ///数组大小 22 int a[N],pre[N]; 23 int main() 24 { 25 int n; 26 while(~scanf("%d",&n)) 27 { 28 memset(pre,0,sizeof(pre)); 29 for(int i=1;i<=n;i++) 30 { 31 scanf("%d",&a[i]); 32 if(a[i]>=N-5)continue; 33 pre[a[i]]++; 34 } 35 int ans=1; 36 for(int i=1;i<=1000000;i++) 37 { 38 pre[i]=pre[i]+pre[i-1]; 39 ans=max(ans,pre[i]/i+(pre[i]%i?以上是关于华中农业大学第五届程序设计大赛网络同步赛解题报告2(转)的主要内容,如果未能解决你的问题,请参考以下文章湖南大学ACM程序设计新生杯大赛(同步赛)J - Piglet treasure hunt Series 2
湖南大学ACM程序设计新生杯大赛(同步赛)A - Array
湖南大学ACM程序设计新生杯大赛(同步赛)B - Build