Codeforces Round #643 (Div.2)
前言:这套cf我感觉出的很不错,AB就不说了,唯一有点欠缺的就是C和D的位置应该换一下,C出的挺不错,反正我当时没有想出来(赛后补题的时候其实也不难。。听朋友说还可以FFT优化,然而我是个图论手并不会数论)。D就是个一眼构造题,也没什么意思。E也是个不错的三分题,至少加强了我对三分的认知。F过的人太少,不补了叭
A:Sequence with Digits
签到题不详细讲了,直接上代码吧...
#include <iostream> #include <algorithm> using namespace std; #define ll long long ll a, b; int main() { int t; cin >> t; while (t--) { cin >> a >> b; int cnt = 1; while (1) { if (cnt == b) break; int ma = 0, mi = 9; ll tmp = a; while (tmp > 0) { int now = tmp % 10; ma = max(ma, now), mi = min(mi, now); tmp /= 10; } if (mi == 0) break; cnt++; a += mi * ma; } cout << a << "\n"; } }
B:Young Explorers
这个题也没什么意思,签到
#include<bits/stdc++.h> #define ll long long #define rep(i,a,n) for(int i=a;i<=n;i++) #define per(i,n,a) for(int i=n;i>=a;i--) #define endl '\n' #define mem(a,b) memset(a,b,sizeof(a)) #define IO ios::sync_with_stdio(false);cin.tie(0); using namespace std; const int INF=0x3f3f3f3f; const ll inf=0x3f3f3f3f3f3f3f3f; const int mod=1e9+7; const int maxn=1e6+5; int a[maxn]; int main(){ int t; cin>>t; while(t--) { int n; cin>>n; for(int i=1;i<=n;i++) { cin>>a[i]; } sort(a+1,a+n+1); int res=0;int sum=0; for(int i=1;i<=n;i++) { sum++; if(a[i]<=sum) { sum=0;res++; } } cout<<res<<endl; } }
C:Count Triangles
解法:很显然,这个题2层for循环肯定爆TLE,那么就需要优化了。众所周知,构成三角形的条件是:x+y>z,那么我可以进行枚举x+y来优化,令m=x+y,算出当x+y和为m的时候,有几种可行的构造数量s2,然后去乘s1=max(m-1,d)-c+1就可以了,前提是s1和s2均非0
∵x+y=m, ∴y=m-x, 又∵B≤y=m-x≤C,∴m-C≤x≤m-B,又因为A≤x≤B,所以取交集,该组数目等于右界-左界+1
#include<bits/stdc++.h> #define ll long long #define rep(i,a,n) for(int i=a;i<=n;i++) #define per(i,n,a) for(int i=n;i>=a;i--) #define endl '\n' #define mem(a,b) memset(a,b,sizeof(a)) #define IO ios::sync_with_stdio(false);cin.tie(0); using namespace std; const int INF=0x3f3f3f3f; const ll inf=0x3f3f3f3f3f3f3f3f; const int mod=1e9+7; const int maxn=5e5+5; int main(){ int a,b,c,d;cin>>a>>b>>c>>d; ll ans=0; for(int i=a+b;i<=b+c;i++){ int s1=min(d,i-1)-c+1; int s2=min(i-b,b)-max(i-c,a)+1; if(s1<0||s2<0) continue; else ans+=1LL*s1*s2; } cout<<ans<<endl; }
D. Game With Array
解法:构造n-1个1和1个s-n+1,判断s-n+1>n的情况是否存在,存在就输出yes,反之输出no
#include<bits/stdc++.h> #define ll long long #define rep(i,a,n) for(int i=a;i<=n;i++) #define per(i,n,a) for(int i=n;i>=a;i--) #define endl '\n' #define pb push_back #define mem(a,b) memset(a,b,sizeof(a)) #define IO ios::sync_with_stdio(false);cin.tie(0); using namespace std; const int INF=0x3f3f3f3f; const ll inf=0x3f3f3f3f3f3f3f3f; const int mod=1e9+7; const int maxn=1e6+5; int a[maxn]; int main(){ int n,s;cin>>n>>s; if(s<=2*n-1) puts("NO"); else{ puts("YES"); for(int i=1;i<n;i++){ cout<<1<<" "; } cout<<s-n+1<<endl; cout<<s-n<<endl; } }
E. Restorer Distance
解法:三分高度,因为这个题是求最小花费,所以图像是与y=x^2很类似,针对曲线求最小值就是三分。另外up就是需要增加的砖块数,down就是需要减少的砖块数。显然总花费=ans=A*up+R*down;倘若A+R>M,那么就需要减少总花费了,此时x=min(up,down),ans+=M*x-x*A-x*R;
#include<bits/stdc++.h> #define ll long long #define rep(i,a,n) for(int i=a;i<=n;i++) #define per(i,n,a) for(int i=n;i>=a;i--) #define endl '\n' #define mem(a,b) memset(a,b,sizeof(a)) #define IO ios::sync_with_stdio(false);cin.tie(0); using namespace std; const int INF=0x3f3f3f3f; const ll inf=0x3f3f3f3f3f3f3f3f; const int mod=1e9+7; const int maxn=1e5+5; int N,A,R,M,a[maxn]; ll check(int mid){ ll ans=0,up=0,down=0; rep(i,1,N){ if(a[i]<mid)up+=mid-a[i]; else down+=a[i]-mid; } ans=A*up+R*down; ll x=min(up,down); if(A+R>M) ans+=M*x-x*A-x*R; return ans; } int main(){ cin>>N>>A>>R>>M; rep(i,1,N) cin>>a[i]; int l=0,r=1e9; while(l<r){ int midl=(r-l)/3+l,midr=r-(r-l)/3; ll suml=check(midl),sumr=check(midr); if(suml>sumr) l=midl+1; else r=midr-1; } ll ans=check(l); cout<<ans<<endl; }
前ICPC算法竞赛退役选手|现摸鱼ing