比赛链接:https://codeforc.es/contest/1714
这次A了 A题B题C题和E题,开题顺序是CBADE,D题没有什么思路就直接跳了。
div3倒着开题名次提升了不少。这次除了A题有些失误意外其他的都还好。
A题:水题,大意是给出小明睡觉的时间,小时和分钟。给出一堆闹钟,求出在第一个闹钟之前能睡多长时间。
这个题刚开始我是去计算的,结果有些测试点没有过去。因为数据量比较小,所以直接暴力过了。
code:
#include<bits/stdc++.h> using namespace std; #pragma GCC optimize(2) int a[26][65]; int main() { ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0); int t; cin>>t; int n,h,m,x,y; while(t--) { memset(a,0,sizeof a); cin>>n>>h>>m; for(int i=1;i<=n;i++) { cin>>x>>y; a[x][y] = 1; } int sum = 0; while(1) { if(a[h][m]==1) { cout<<sum/60<<' '<<sum%60<<endl; break; } sum++; m++; if(m>=60) m%=60,h++; if(h>=24) h%=24; } } }
B题:大意是给出n个数,然后每次能够删除开头第一个数,求出最少删除多少数能够使得剩下的数互不相同。
解决方法:直接倒着数一遍,直到出现重复。数据量不大可以直接哈希记录,如果数据大可以map做伪哈希。
code:
#include<bits/stdc++.h> using namespace std; #pragma GCC optimize(2) const int nn = 2*1e5+10; bool sign[nn]; vector<int>ve; int main() { ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0); int t; cin>>t; while(t--) { ve.clear(); memset(sign,false,sizeof sign); int n,x; cin>>n; for(int i=1;i<=n;i++) { cin>>x; ve.push_back(x); } int i=ve.size()-1; for(;i>=0;i--) { if(sign[ve[i]]) break; sign[ve[i]]=true; } cout<<i+1<<endl; } }
C题:大意是给出一个数字n,求出一个数,这个数由1-9互不相同的数组成,其和为n且最小。
解决方法:从最大的数开始搜,放到最后倒着输出。
code:
#include<bits/stdc++.h> using namespace std; #pragma GCC optimize(2) bool sign[10]; int n; vector<int>ve; bool flag; void dfs(int k,int sum) { if(flag == true ) return; if(sum==n) { for(int i=ve.size()-1;i>=0;i--) cout<<ve[i]; cout<<endl; flag = true; return; }else if(sum>n) return; for(int i=k;i>=1;i--) { ve.push_back(i); dfs(k-1,sum+i); ve.pop_back(); } } int main() { ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0); int t; cin>>t; while(t--) { flag = false; ve.clear(); cin>>n; dfs(9,0); } }E题:给出一堆数,每次可以令这些数加上 这个数%10的数。通过不限次数的操作能否使得这些数相等。分情况讨论:如果存在%10==0,则所有的数所达到这个状态且需要相等。否则,任意一个数通过+%10的数可以到达2。例如14-18-26-32 ,13-16-22。要想使得所有数相等,可以让他们到达一个2的状态,从一个2的状态到达另一个2的状态中间相隔20(2-4-8-16-22),求出差距是否是20的倍数。code:
#include<bits/stdc++.h> using namespace std; #pragma GCC optimize(2) #define ll long long const int nn = 2e5+10; const int maxn = 1e9+10; vector<ll>ve; int main() { ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0); int t; cin>>t; while(t--) { ve.clear(); ll n,x; cin>>n; for(int i=1;i<=n;i++) { cin>>x; ve.push_back(x); } for(int i=0;i<ve.size();i++) { while(ve[i]%10!=2&&ve[i]%10!=0) ve[i]+=ve[i]%10; } sort(ve.begin(),ve.end()); if(ve[0]%10==2) { int i=0; for(;i<ve.size()-1;i++) { if((ve[i+1]-ve[i])%20!=0) break; } if(i<ve.size()-1) printf("NO\n"); else printf("YES\n"); }else { int i=0; for(;i<ve.size()-1;i++) { if(ve[i+1]!=ve[i]) break; } if(i<ve.size()-1) printf("NO\n"); else printf("YES\n"); } } }
D题:大意是给出一个字符串,然后给出n个字符串(我们命名为子串)。子串可以无限次使用,求出最少通过多少个子串可以将主串染色。如果不能染色输出-1,否则输出每个子串染色的区间。格式为,子串编号 开始下标。
贪心思想去考虑。因为主串长度不大,我们可以暴力出它的所有子串,然后和n个字符串去比较,将所有的符合条件的子串和位置进行记录。我们可以得到一个段向量。问题变成了在一个段向量中,求出组成一条线的最优方案,这一步可以贪心,复杂度不到n*段数,暴力匹配复杂度n^3,。差不多能过。
code:
#include<bits/stdc++.h> using namespace std; #pragma GCC optimize(2) struct duan{ int str; int begint; }; bool cmp(duan a,duan b) { return a.begint<b.begint; } int main() { //ios_base::sync_with_stdio(0); cin.tie(0); //cout.tie(0); int t; cin>>t; while(t--) { vector<duan> ve; vector<duan> ans; string a; cin>>a; int n; cin>>n; string z[11]; for(int i=1;i<=n;i++) cin>>z[i]; for(int k=1;k<=n;k++) { for(int i=0;i<a.size();i++) { for(int j=1;j<=a.size()-i;j++) { if(a.substr(i,j)==z[k]) ve.push_back({k,i}); } } } sort(ve.begin(),ve.end(),cmp); for(int i=0;i<a.size();) { int lasti = i; int tt = 0, pos = 0; for(int j=0;j<ve.size();j++) { if((ve[j].begint<=i) && (tt==0||ve[j].begint+z[ve[j].str].size()>pos+z[tt].size())) { tt = ve[j].str,pos = ve[j].begint; } } i = pos+z[tt].size(); if(tt==0&&pos==0||lasti == i) { ans.clear(); break; } else ans.push_back({tt,pos+1}); } if(ans.size()==0) cout<<-1<<endl; else { cout<<ans.size()<<endl; for(int i=0;i<ans.size();i++) cout<<ans[i].str<<' '<<ans[i].begint<<endl; } } }

Reply