2018 “百度之星”程序设计大赛 - 初赛(A)
Posted bobhuang
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2018 “百度之星”程序设计大赛 - 初赛(A)相关的知识,希望对你有一定的参考价值。
度度熊拼三角
度度熊有 NN 根木棒,每根木棒的长度为a_ia?i??。
现在要挑选其中的三根,问能拼出的三角形的最大周长是多少。
如果不能拼成任何一个三角形,输出 -1?1。
多组数据(不超过1010组),读到EOF结束。
对于每一组数据:
第一行一个数 NN 表示木棒数量。
第二行一共 NN 个数,描述每一根木棒的长度。
1 leq N leq 10001≤N≤1000
木棒长度都是不超过100000100000的正整数
对于每一组数据,输出一个数表示答案。
3 1 1 100 7 1 9 9 90 2 2 4
-1 22
A最大的连续选三根
两边之和大于第三边推广就是两小边大于大边就好了
#include<bits/stdc++.h> using namespace std; const int N=1005; int a[N]; int main() { ios::sync_with_stdio(false),cin.tie(0),cout.tie(0); int n; while(cin>>n) { for(int i=0; i<n; i++)cin>>a[i]; sort(a,a+n); int ans=-1; for(int i=n-3; i>=0; i--) if(a[i]+a[i+1]>a[i+2]) { ans=a[i]+a[i+1]+a[i+2]; break; } cout<<ans<<" "; } return 0; }
本来sb的n^2logn的写法
#include<stdio.h> #include<bits/stdc++.h> using namespace std; #define lson l,(l+r)/2,rt<<1 #define rson (l+r)/2+1,r,rt<<1|1 #define dbg(x) cout<<#x<<" = "<< (x)<< endl #define pb push_back #define fi first #define se second #define ll long long #define sz(x) (int)(x).size() #define pll pair<long long,long long> #define pii pair<int,int> #define pq priority_queue const int N=1e5+5,MD=1e9+7,INF=0x3f3f3f3f; const ll LL_INF=0x3f3f3f3f3f3f3f3f; const double eps=1e-9,e=exp(1),PI=acos(-1.); int a[N]; int main() { ios::sync_with_stdio(false),cin.tie(0),cout.tie(0); int n; while(cin>>n) { int a[1005]; for(int i=0; i<n; i++)cin>>a[i]; sort(a,a+n); int ans=-1; for(int i=0;i<n;i++) for(int j=i+1;j<n;j++) { int y=a[j]+a[i]; int pos=lower_bound(a+j+1,a+n,y)-a; if(pos-1==j)continue; ans=max(ans,a[i]+a[j]+a[pos-1]); } cout<<ans<<" "; } return 0; }
度度熊学队列
度度熊正在学习双端队列,他对其翻转和合并产生了很大的兴趣。
初始时有 NN 个空的双端队列(编号为 11 到 NN ),你要支持度度熊的 QQ 次操作。
①11 uu ww valval 在编号为 uu 的队列里加入一个权值为 valval 的元素。(w=0w=0 表示加在最前面,w=1w=1 表示加在最后面)。
②22 uu ww 询问编号为 uu 的队列里的某个元素并删除它。( w=0w=0 表示询问并操作最前面的元素,w=1w=1 表示最后面)
③33 uu vv ww 把编号为 vv 的队列“接在”编号为 uu 的队列的最后面。w=0w=0 表示顺序接(队列 vv 的开头和队列 uu 的结尾连在一起,队列vv 的结尾作为新队列的结尾), w=1w=1 表示逆序接(先将队列 vv 翻转,再顺序接在队列 uu 后面)。且该操作完成后,队列 vv 被清空。
有多组数据。
对于每一组数据,第一行读入两个数 NN 和 QQ。
接下来有 QQ 行,每行 33~44 个数,意义如上。
N leq 150000,Q leq 400000N≤150000,Q≤400000
1 leq u,v leq N,0 leq w leq 1,1 leq val leq 1000001≤u,v≤N,0≤w≤1,1≤val≤100000
所有数据里 QQ 的和不超过500000500000
对于每组数据的每一个操作②,输出一行表示答案。
注意,如果操作②的队列是空的,就输出-1?1且不执行删除操作。
2 10 1 1 1 23 1 1 0 233 2 1 1 1 2 1 2333 1 2 1 23333 3 1 2 1 2 2 0 2 1 1 2 1 0 2 1 1
23 -1 2333 233 23333 提示 由于读入过大,C/C++ 选手建议使用读入优化。 一个简单的例子: void read(int &x){ char ch = getchar();x = 0; for (; ch < ‘0‘ || ch > ‘9‘; ch = getchar()); for (; ch >=‘0‘ && ch <= ‘9‘; ch = getchar()) x = x * 10 + ch - ‘0‘; }
B不卡时间,不像上次ZOJ月赛还卡时间,直接过就行了
#include<bits/stdc++.h> using namespace std; void read(int &x) { char ch = getchar(); x = 0; for (; ch < ‘0‘ || ch > ‘9‘; ch = getchar()); for (; ch >=‘0‘ && ch <= ‘9‘; ch = getchar()) x = x * 10 + ch - ‘0‘; } list<int>li[150005]; int main() { int n,q; while(~scanf("%d%d",&n,&q)) { for(int i=1; i<=n; i++)li[i].clear(); for(int i=1,op,u,v,w,val; i<=q; i++) { read(op); switch(op) { case 1: { read(u),read(w),read(val); if(w==1)li[u].push_back(val); else li[u].push_front(val); break; } case 2: { read(u),read(w); if(w==1) { if(li[u].empty())printf("-1 "); else { printf("%d ",*li[u].rbegin()),li[u].pop_back(); } } else { if(li[u].empty())printf("-1 "); else printf("%d ",*li[u].begin()),li[u].pop_front(); } break; } case 3: { read(u),read(v),read(w); if(w==1)li[v].reverse(),li[u].splice(li[u].end(),li[v]),li[v].clear(); else li[u].splice(li[u].end(),li[v]),li[v].clear(); } } } } return 0; }
度度熊剪纸条
度度熊有一张纸条和一把剪刀。
纸条上依次写着 NN 个数字,数字只可能是 00 或者 11。
度度熊想在纸条上剪 KK 刀(每一刀只能剪在数字和数字之间),这样就形成了 K+1K+1 段。
他再把这 K+1K+1 段按一定的顺序重新拼起来。
不同的剪和接的方案,可能会得到不同的结果。
度度熊好奇的是,前缀 11 的数量最多能是多少。
有多组数据,读到EOF结束。
对于每一组数据,第一行读入两个数 NN 和 KK 。
第二行有一个长度为 NN 的字符串,依次表示初始时纸条上的 NN 个数。
0 leq K < N leq 100000≤K<N≤10000
所有数据 NN 的总和不超过100000100000
对于每一组数据,输出一个数,表示可能的最大前缀 11 的数量。
5 1 11010 5 2 11010
2 3
可以考虑在哪里下刀,肯定是在1将要开始的地方,然后头尾也是特殊的
#include <bits/stdc++.h> using namespace std; #define fi second #define se first const int N=10005; int a[N],dp[N]; char s[N]; pair<int,int>P[N]; int main() { ios::sync_with_stdio(false),cin.tie(0),cout.tie(0); int n,k; while(cin>>n>>k) { cin>>s; int tot=0; for(int i=0; i<N; i++)P[i].fi=P[i].se=0; memset(dp,0,sizeof dp); for(int i=0; i<n; i++) { if(s[i]==‘1‘) P[tot].fi++; else tot++; } if(s[0]==‘1‘) P[0].se=1; if(s[n-1]==‘1‘) P[tot].se=1,tot++; if(k==0) { if(s[0]==‘1‘) cout<<P[0].fi<<" "; else cout<<"0 "; } else { int sum=0; if(s[0]==‘1‘) sum+=P[0].fi; if(s[n-1]==‘1‘&&tot!=1) sum+=P[tot-1].fi; sort(P,P+tot,greater<pair<int,int> >()); int pos=0; while(P[pos].se&&tot<n)pos++; P[pos].se=1; for(int j=0; j<tot; j++) { for(int i=k; i>1; i--)dp[i]=max(dp[i],dp[i-2+P[j].se]+P[j].fi); if(P[j].se==1)dp[1]=max(dp[1],dp[0]+P[j].fi); } cout<<max(sum,dp[k])<<" "; } } return 0; }
还有一种写法
#include <bits/stdc++.h> using namespace std; const int maxn = 10005; int n, k, f[maxn]; string s; int solve() { vector<pair<int, int>> vec; int p = 0; while(p < n) { if(s[p] == ‘1‘) { int j = p, tot = 0; while(j < n && s[j] == ‘1‘) { tot++, j++; } if(p == 0) vec.push_back(make_pair(tot, 1)); else if(j == n) vec.push_back(make_pair(tot, 1)); else vec.push_back(make_pair(tot, 2)); p = j; } else p++; } if(k == 1) { if(s[0] == ‘1‘) return vec[0].first; return 0; } memset(f, 0, sizeof(f)); for(int i = 0; i < vec.size(); i++) for(int j = k; j >= vec[i].second; j--) f[j] = max(f[j], f[j-vec[i].second]+vec[i].first); return f[k]; } int main() { while(cin >> n >> k) { cin >> s;k++; cout << solve() << endl; } }
度度熊看球赛
世界杯正如火如荼地开展!度度熊来到了一家酒吧。
有 NN 对情侣相约一起看世界杯,荧幕前正好有 2 imes N2×N 个横排的位置。
所有人都会随机坐在某个位置上。
当然,如果某一对情侣正好挨着坐,他们就会有说不完的话,影响世界杯的观看。
一般地,对于一个就座方案,如果正好有 KK 对情侣正好是挨着坐的,就会产生 D^KD?K?? 的喧闹值。
度度熊想知道随机就座方案的期望喧闹值。
为了避免输出实数,设答案为 ansans,请输出 ans imes (2N)!ans×(2N)! modmod PP 的值。其中 P=998244353P=998244353
有多组数据(不超过 10001000 组),读到EOF结束。
对于每一组数据,读入两个数 NN 和 DD 。
1 leq N,D leq 10001≤N,D≤1000
对于每一组数据,输出一个数表示答案。
1 10 2 3
20 104
读错题,竟然是一排有2*n个座位,然后找到递推式就好了
#include<bits/stdc++.h> using namespace std; int dp[1005][1005],C[2005][2005]; const int MD=998244353; int main() { int i,j; for (i=0; i<2005; i++) { C[i][0]=1; for (j=1; j<=i; j++) C[i][j]=(C[i-1][j-1]+C[i-1][j])%MD; } dp[0][0]=1; for(i=1; i<1005; i++) //2i个位置 j个相邻 { for (j=0; j<i; j++) { if(dp[i-1][j]==0)continue; int t=(i-1)*2-j+1;//不会造成影响 dp[i][j+1]=(dp[i][j+1]+2LL*dp[i-1][j]*C[t][1]%MD)%MD;//组1 dp[i][j]=(dp[i][j]+2LL*dp[i-1][j]*C[t][2]%MD)%MD;//没有贡献 if(j>0)dp[i][j-1]=(dp[i][j-1]+2LL*dp[i-1][j]*C[t][1]%MD*C[j][1]%MD)%MD;//拆1 if(j>1)dp[i][j-2]=(dp[i][j-2]+2LL*dp[i-1][j]*C[j][2]%MD)%MD;//拆2 dp[i][j]=(dp[i][j]+2LL*dp[i-1][j]*C[j][1]%MD)%MD;//拆1+组1 } } int n,K; while (~scanf("%d%d",&n,&K)) { int ans=0,t=1; for(i=0; i<=n; i++)ans=(ans+1LL*t*dp[n][i])%MD,t=1LL*t*K%MD; printf("%d ",ans); } return 0; }
以上是关于2018 “百度之星”程序设计大赛 - 初赛(A)的主要内容,如果未能解决你的问题,请参考以下文章
2018 “百度之星”程序设计大赛 - 初赛(A)度度熊学队列 list rope