【Educational Codeforces Round 53 (Rated for Div. 2)】
前言
好久不打cf,为了晚上的edu自己开了一场vp好久不打cf,为了晚上的edu自己开了一场vp好久不打cf,为了晚上的edu自己开了一场vp
战绩还算可以,只是好久不打前期题卡的时间有点长战绩还算可以,只是好久不打前期题卡的时间有点长战绩还算可以,只是好久不打前期题卡的时间有点长
但是看榜D最开始过的多就去写D,发现就是个简单模拟,由于break写少wa了一发之后就过了但是看榜D最开始过的多就去写D,发现就是个简单模拟,由于break写少wa了一发之后就过了但是看榜D最开始过的多就去写D,发现就是个简单模拟,由于break写少wa了一发之后就过了
回来写c发现是个码力题,码码码就过了。回来写c发现是个码力题,码码码就过了。回来写c发现是个码力题,码码码就过了。
刷专题对打cf的提升还是很大的,下一年争取打满cf吧刷专题对打cf的提升还是很大的,下一年争取打满cf吧刷专题对打cf的提升还是很大的,下一年争取打满cf吧 O(∩_∩)O
无惧掉分
A. Diverse Substring
题意
求一个长度为n的字符串是否存在一个子串,满足子串中出现最多次数的字符出现次数<=len/2求一个长度为n的字符串是否存在一个子串,满足子串中出现最多次数的字符出现次数<=len/2求一个长度为n的字符串是否存在一个子串,满足子串中出现最多次数的字符出现次数<=len/2
n<=1e3n<=1e3n<=1e3
做法
直接找是否有两个连续的不同的字符,输出就可以直接找是否有两个连续的不同的字符,输出就可以直接找是否有两个连续的不同的字符,输出就可以
坑点
直接暴力枚举所有子串维护一个出现次数最多的字符的出现次数就好直接暴力枚举所有子串维护一个出现次数最多的字符的出现次数就好直接暴力枚举所有子串维护一个出现次数最多的字符的出现次数就好
简单题想不到好做法的时候直接暴力简单题想不到好做法的时候直接暴力简单题想不到好做法的时候直接暴力
代码
#include<stdio.h> #include<iostream> #include<algorithm> #include<string.h> using namespace std; const int maxn = 1e5+10; char str[maxn]; int sum[30]; int main() { int len; scanf("%d%s",&len,str); for(int i=1;i<len;i++) { if(str[i]!=str[i-1]) { printf("YES\n"); cout<<str[i-1]<<str[i]<<endl; return 0; } } printf("NO\n"); return 0; }
B. Vasya and Books
题意
给你一些书,每本书有自己的编号a[i],每本书从下到上叠在一起给你一些书,每本书有自己的编号a[i],每本书从下到上叠在一起给你一些书,每本书有自己的编号a[i],每本书从下到上叠在一起
然后每次你要买编号为b[i]的书和他上面得所有书,输出每次能买到多少本书然后每次你要买编号为b[i]的书和他上面得所有书,输出每次能买到多少本书然后每次你要买编号为b[i]的书和他上面得所有书,输出每次能买到多少本书
n<=2∗105n<=2*10^5n<=2∗105
做法
类似单调栈的思想,如果之前买过比当前要买的书深度更深的,那么这次就什么都买不到类似单调栈的思想,如果之前买过比当前要买的书深度更深的,那么这次就什么都买不到类似单调栈的思想,如果之前买过比当前要买的书深度更深的,那么这次就什么都买不到
所以我们只需要维护一个深度最大值,每次只买深度最大值与当前深度之间的书,并更新深度最大值所以我们只需要维护一个深度最大值,每次只买深度最大值与当前深度之间的书,并更新深度最大值所以我们只需要维护一个深度最大值,每次只买深度最大值与当前深度之间的书,并更新深度最大值
代码
#include<stdio.h> #include<iostream> #include<algorithm> #include<string.h> using namespace std; const int maxn = 2e5+10; int a[maxn],b[maxn]; int mp[maxn]; int main() { int n; scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%d",&a[i]); mp[a[i]]=i; } for(int i=1;i<=n;i++) scanf("%d",&b[i]); int maxx=0; for(int i=1;i<=n;i++) { int tmp=mp[b[i]]; printf("%d ",max(0,tmp-maxx)); maxx=max(maxx,tmp); } return 0; }
C. Vasya and Robot
题意
在二维平面上有一个机器人最开始在点(0,0)处在二维平面上有一个机器人最开始在点(0,0)处在二维平面上有一个机器人最开始在点(0,0)处
最终他要走到点(x,y)处,现在给出行动路线,有(L,R,U,D)四种走法最终他要走到点(x,y)处,现在给出行动路线,有(L,R,U,D)四种走法最终他要走到点(x,y)处,现在给出行动路线,有(L,R,U,D)四种走法
每次他可以修改某个区间内的走法,问需要修改的最小区间长度是多少每次他可以修改某个区间内的走法,问需要修改的最小区间长度是多少每次他可以修改某个区间内的走法,问需要修改的最小区间长度是多少
(区间内可以修改为任意走法,也可以不修改)(区间内可以修改为任意走法,也可以不修改)(区间内可以修改为任意走法,也可以不修改)
n<=2∗105n<=2*10^5n<=2∗105
做法
这个数据范围大概只能想二分,二分长度之后枚举每个点作为区间起点是否能走到(x,y)这个数据范围大概只能想二分,二分长度之后枚举每个点作为区间起点是否能走到(x,y)这个数据范围大概只能想二分,二分长度之后枚举每个点作为区间起点是否能走到(x,y)
check的过程就是先把区间之外的走法走完,得到(x1,y1)check的过程就是先把区间之外的走法走完,得到(x1,y1)check的过程就是先把区间之外的走法走完,得到(x1,y1)
再判断(x1,y1)与(x,y)的曼哈顿距离D再判断(x1,y1)与(x,y)的曼哈顿距离D再判断(x1,y1)与(x,y)的曼哈顿距离D
如果当前区间长度len>D而且(len−D)Mod2==0,就代表机器人可以通过当前区间走到(x,y)如果当前区间长度len>D而且(len-D)Mod2==0,就代表机器人可以通过当前区间走到(x,y)如果当前区间长度len>D而且(len−D)Mod2==0,就代表机器人可以通过当前区间走到(x,y)
代码
#include<stdio.h> #include<iostream> #include<algorithm> #include<map> using namespace std; #define dbg(x) cout<<#x<<" = "<<x<<endl const int maxn = 2e5+10; char s[maxn]; int x,y; int n,sum[maxn][4];//U D L R map<char,int> mp; int n1,n2,n3,n4; bool check(int mid) { int sum1=0,sum2=0,sum3=0,sum4=0; for(int i=1;i<=n-mid+1;i++) { sum1=sum[i-1][0]+sum[n][0]-sum[i+mid-1][0]; sum2=sum[i-1][1]+sum[n][1]-sum[i+mid-1][1]; sum3=sum[i-1][2]+sum[n][2]-sum[i+mid-1][2]; sum4=sum[i-1][3]+sum[n][3]-sum[i+mid-1][3]; int xx=0,yy=0; n1=0,n2=0,n3=0,n4=0; xx+=(sum4-sum3); yy+=(sum1-sum2); if(xx>=x) n3=xx-x; else n4=x-xx; if(yy>=y) n2=yy-y; else n1=y-yy; if(n1+n2+n3+n4<=mid&&(mid-n1-n2-n3-n4)%2==0) return true; } return false; } int main() { mp['U']=0; mp['D']=1; mp['L']=2; mp['R']=3; scanf("%d%s",&n,s+1); for(int i=1;i<=n;i++) { sum[i][0]=sum[i-1][0]; sum[i][1]=sum[i-1][1]; sum[i][2]=sum[i-1][2]; sum[i][3]=sum[i-1][3]; sum[i][mp[s[i]]]++; } scanf("%d%d",&x,&y); int l=0,r=n,mid; while(l<=r) { int mid=(l+r)/2; if(check(mid)) r=mid-1; else l=mid+1; } if(l==n+1) printf("-1\n"); else printf("%d\n",l); return 0; }
D. Berland Fair
题意
有n个商品排列成一行,每个商品有一个加个a[i],最初你身上有T元有n个商品排列成一行,每个商品有一个加个a[i],最初你身上有T元有n个商品排列成一行,每个商品有一个加个a[i],最初你身上有T元
每次都从左到右走,如果买的起这个商品就买一件,买不起就不买每次都从左到右走,如果买的起这个商品就买一件,买不起就不买每次都从左到右走,如果买的起这个商品就买一件,买不起就不买
每次走到头就重新从左端走,问最后能买到多少件商品每次走到头就重新从左端走,问最后能买到多少件商品每次走到头就重新从左端走,问最后能买到多少件商品
n<=2∗105 1<=T<=1018n<=2*10^5 \ \ \ \ 1<=T<=10^{18}n<=2∗105 1<=T<=1018
做法
由于T比较大,我们肯定要用到除法由于T比较大,我们肯定要用到除法由于T比较大,我们肯定要用到除法
每次我们统计当前可买的商品的价值总和now每次我们统计当前可买的商品的价值总和now每次我们统计当前可买的商品的价值总和now
若T>now,则下次遍历一次所有商品还是这么买若T>now,则下次遍历一次所有商品还是这么买若T>now,则下次遍历一次所有商品还是这么买
否则我们就重新判断当前可以购买哪些商品否则我们就重新判断当前可以购买哪些商品否则我们就重新判断当前可以购买哪些商品
但是我们要考虑所有商品都小于T,但是不能一起购买的数据但是我们要考虑所有商品都小于T,但是不能一起购买的数据但是我们要考虑所有商品都小于T,但是不能一起购买的数据
我们就要从前往后模拟一遍更新一次T我们就要从前往后模拟一遍更新一次T我们就要从前往后模拟一遍更新一次T
再重新统计所有小于T的商品的价值和再重新统计所有小于T的商品的价值和再重新统计所有小于T的商品的价值和
最后直到一个物品也购买不了退出循环最后直到一个物品也购买不了退出循环最后直到一个物品也购买不了退出循环
代码
#include<stdio.h> #include<iostream> #include<algorithm> #include<string.h> using namespace std; typedef long long ll; const int maxn = 2e5+10; ll a[maxn]; int main() { int n; ll T; scanf("%d%lld",&n,&T); for(int i=1;i<=n;i++) scanf("%lld",&a[i]); ll ans=0; while(T) { ll sum=0; ll cnt=0; for(int i=1;i<=n;i++) { if(a[i]<=T) { cnt++; sum+=a[i]; } } if(cnt==0) break; if(T<sum) { for(int i=1;i<=n;i++) { if(T>=a[i]) { ans++; T-=a[i]; } } } else { ans+=1LL*cnt*(T/sum); T=T%sum; } } printf("%lld\n",ans); return 0; }
E. Segment Sum
题意
题意很简单,求l到r之间的所有数中不同数位数不超过k的数之和题意很简单,求l到r之间的所有数中不同数位数不超过k的数之和题意很简单,求l到r之间的所有数中不同数位数不超过k的数之和
1<=l<=r<=1018 1<=k<=101<=l<=r<=10^{18} \ \ 1<=k<=101<=l<=r<=1018 1<=k<=10
做法
一眼就知道是数位dp一眼就知道是数位dp一眼就知道是数位dp
而且我们也很容易想到状态的定义而且我们也很容易想到状态的定义而且我们也很容易想到状态的定义
数位dp时要往下传递都有哪些数位出现过,这个状态是(1<<10)的数位dp时要往下传递都有哪些数位出现过,这个状态是(1<<10)的数位dp时要往下传递都有哪些数位出现过,这个状态是(1<<10)的
由于我们要统计和,每个状态要保存两个值由于我们要统计和,每个状态要保存两个值由于我们要统计和,每个状态要保存两个值
满足状态的数字个数和当前状态数字对答案的贡献满足状态的数字个数和当前状态数字对答案的贡献满足状态的数字个数和当前状态数字对答案的贡献
坑点
由于本题中前导0对状态有影响,注意数位dp时前导0的问题由于本题中前导0对状态有影响,注意数位dp时前导0的问题由于本题中前导0对状态有影响,注意数位dp时前导0的问题
代码
#include<stdio.h> #include<iostream> #include<algorithm> #include<string.h> using namespace std; typedef long long ll; const ll Mod = 998244353ll; typedef pair<ll,ll> pll; #define Se second #define Fi first ll l,r,k; ll pow_[20]; int cal(ll x) { int ans=0; while(x) { if(x&1) ans++; x/=2; } return ans; } pll dp[20][1<<12][2]; ll a[20]; pll dfs(ll len,ll state,bool limit,bool lead) { if(len==0) return pll(1,0);//遍历结束,无需算对答案的贡献,但是要像正常数位dp一样统计满足条件的个数 if(!limit&&dp[len][state][lead].Se) return dp[len][state][lead];//注意带前导0的数位dp套路 pll ans=pll(0,0); int up=limit?a[len]:9; for(int i=0;i<=up;i++) { ll temp=state|((lead||i)<<i); //若当前有前导0而且当前数位为0,则状态不更新 if(cal(temp)>k) continue; //不满足答案的状态要去掉 pll tmp=dfs(len-1,temp,limit&&i==a[len],lead||i); ans.Fi=(ans.Fi+tmp.Fi)%Mod; ans.Se=(ans.Se+tmp.Se+(1LL*i*pow_[len-1]%Mod*tmp.Fi)%Mod)%Mod; //当前数位对答案的贡献为当前数位所代表的值为i*pow[len-1] //当前数位为i的数字个数为tmp.Fi //总贡献为:i*pow_[len-1]%Mod*tmp.Fi } return dp[len][state][lead]=ans; } ll solve(ll x) { for(int i=0;i<20;i++) { for(int j=0;j<(1<<12);j++) { for(int l=0;l<2;l++) { dp[i][j][l].Fi=0; dp[i][j][l].Se=0; } } } memset(a,0,sizeof(a)); int len=0; while(x) { a[++len]=x%10; x/=10; } return dfs(len,0,true,0).Se%Mod; } int main() { pow_[0]=1; for(int i=1;i<20;i++) pow_[i]=pow_[i-1]*10%Mod;//每一位的贡献预处理 scanf("%lld%lld%lld",&l,&r,&k); printf("%lld\n",(solve(r)-solve(l-1)+Mod)%Mod); return 0; }阅读更多
- 【Educational Codeforces Round 53 (Rated for Div. 2) E. Segment Sum】 数位DP
- 【Educational Codeforces Round 53 (Rated for Div. 2)】
- 【Educational Codeforces Round 53 (Rated for Div. 2)-C. Vasya and Robot】二分
- Educational Codeforces Round 39 (Rated for Div. 2)(A-D)(水题 + 模拟 + 贪心模拟 + DP)
- Educational Codeforces Round 34 (Rated for Div. 2) D - Almost Difference
- Educational Codeforces Round 36 (Rated for Div. 2) A-C
- Educational Codeforces Round 33 (Rated for Div. 2) A - Chess For Three
- Educational Codeforces Round 33 (Rated for Div. 2) A-C题解
- Codeforece Educational Codeforces Round 34 (Rated for Div. 2) (A-D)题解
- Educational Codeforces Round 38 (Rated for Div. 2)A. Word Correction
- Educational Codeforces Round 38 (Rated for Div. 2)
- Educational Codeforces Round 40 (Rated for Div. 2)
- Educational Codeforces Round 40 (Rated for Div. 2)
- Educational Codeforces Round 35 (Rated for Div. 2) F. Tree Destruction
- Codeforces Educational Codeforces Round 42 (Rated for Div. 2) D,E,F
- Educational Codeforces Round 33 (Rated for Div. 2) A题. Chess For Three
- Educational Codeforces Round 33 (Rated for Div. 2) B - Beautiful Divisors
- Educational Codeforces Round 48 (Rated for Div. 2)——A. Death Note ##
- 【Educational Codeforces Round 48 (Rated for Div. 2) C】 Vasya And The Mushrooms
- Educational Codeforces Round 33 (Rated for Div. 2) F - Subtree Minimum Query