Codeforces Round #506 (Div. 3) 題解
Codeforces Round #506 (Div. 3)
題目總鏈接:https://codeforces.com/contest/1029
A. Many Equal Substrings
題意:
給出長度為n的字符串,然後要求你添加一些字符,使得有k個這樣的字符串。
題解:
直接暴力吧...一個指針從1開始,另一個從2開始,逐一比較看是否相同;如果不同,第一個指針繼續回到1,第二個指針從3開始...就這麽一直重復。最後如果第二個指針能夠順利到最後一位,那麽記錄當前的第一個指針,把他後面的串取出來添加k-1個就ok了。
代碼如下:
#include <bits/stdc++.h> usingView Codenamespace std; typedef long long ll; const int N = 55; string s; int n,k; int main(){ cin>>n>>k; cin>>s; int fir = 0,last = 1; for(int i=1;i<n;i++){ if(s[fir]==s[i]) fir++; else if(fir) fir = 0,i=last+1,last=i; } string tmp = s.substr(fir,n);for(int i=1;i<k;i++) s+=tmp; cout<<s; return 0; }
B. Creating the Contest
題意:
給出n個數,選出最長的區間,滿足區間中的相鄰兩個數a,b有2*a>=b且a<b。
題解:
枚舉+判斷一下就ok了。
代碼如下:
#include <bits/stdc++.h> using namespace std; typedef long long ll ; const int N = 2e5+5; ll a[N];View Codeint n; int main(){ scanf("%d",&n); int l=1,r=1,ans=1; for(int i=1;i<=n;i++) scanf("%d",&a[i]); for(int i=2;i<=n;i++){ if(a[i]<=a[i-1]*2){ r++; ans=max(ans,r-l+1); }else{ l=r=i; } } cout<<ans; return 0; }
C. Maximal Intersection
題意:
給出n個區間,然後你可以任意去掉一個區間,最後求區間交集的最大值為多少。
題解:
區間的交集就是[maxl,minr]...根據這個求出前綴、後綴的l和r,然後枚舉去掉哪個區間就行了。註意一下這裏區間的交集是所有區間的交集。
代碼如下:
#include <bits/stdc++.h> #define INF 0x3f3f3f3f using namespace std; typedef long long ll; const int N = 3e5+5; int n; struct line{ int l,r; }p[N]; int prel[N],prer[N],sufl[N],sufr[N]; int main(){ scanf("%d",&n); memset(prer,INF,sizeof(prer)); memset(sufr,INF,sizeof(sufr)); for(int i=1;i<=n;i++) scanf("%d%d",&p[i].l,&p[i].r); for(int i=1;i<=n;i++){ prel[i]=max(prel[i-1],p[i].l); prer[i]=min(prer[i-1],p[i].r); } for(int i=n;i>=1;i--){ sufl[i]=max(sufl[i+1],p[i].l); sufr[i]=min(sufr[i+1],p[i].r); } int ans = 0; for(int i=1;i<=n;i++){ int l = max(prel[i-1],sufl[i+1]); int r = min(prer[i-1],sufr[i+1]); ans=max(ans,r-l); } printf("%d",ans); return 0; }View Code
D. Concatenated Multiples
題意:
給出n個數以及k,現在將任意兩個數聚合成為一對,比如12和345聚合就為12345,問一共有多少對能被k整除。
題解:
將a,b聚合,聚合之後的數即位a*10^len(b)+b,如果滿足(a*10^len(b)+b%k)==0,則有a*10^len(b)%k+b%k=k or 0。
根據這個來寫就好了,最後時間復雜度為O(10*nlogn)。
代碼如下:
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int N = 2e5+5; ll n,k; ll a[N],b[N],len[N],q[12]; vector <ll> vec[12]; int main(){ scanf("%I64d%I64d",&n,&k); q[0]=1; for(int i=1;i<=10;i++) q[i]=q[i-1]*10%k; for(int i=1;i<=n;i++) scanf("%I64d",&a[i]); sort(a+1,a+n+1); for(int i=1;i<=n;i++) b[i]=a[i]; for(int i=1;i<=n;i++){ ll x=a[i]; int cnt=0; while(x){ x/=10; cnt++; } len[i]=cnt; } for(int i=1;i<=10;i++){ for(int j=1;j<=n;j++) vec[i].push_back(a[j]*q[i]%k); sort(vec[i].begin(),vec[i].end()); } ll ans = 0; for(int i=1;i<=n;i++){ b[i]%=k; int l = len[i]; int pos1 = lower_bound(vec[l].begin(),vec[l].end(),(k-b[i])%k)-vec[l].begin(); int pos2 = upper_bound(vec[l].begin(),vec[l].end(),(k-b[i])%k)-vec[l].begin(); ans+=(pos2-pos1); if(a[i]*q[l]%k==(k-b[i])%k)ans--; } printf("%I64d",ans); return 0; }View Code
F. Multicolored Markers
題意:
給出a和b,代表兩種顏色的格子數目。現在用他們圍成一個矩形,還要要求至少有一種顏色圍成一個矩形。現在求最短周長為多少。
題解:
用sqrt(a+b)的時間復雜度可以求出大矩形的因子有哪些。然後枚舉每個因子,再來判斷一下a or b是否能在我們枚舉出來的長以及寬內圍成一個矩形就行了。
我的做法時間復雜度比較高,說一個時間復雜度比較低的解法吧。
就是假定我們現在來判斷a是否能圍成矩形,那麽我們要用sqrt(a)的時間復雜度來求出所有的因子,我們把寬度從小到大來存。對於大矩形也是這樣。然後如果大矩形確定了長l,寬w,那麽小矩形我們就貪心得選擇最大的寬w‘同時滿足w‘<=w,那麽此時l‘就是最小,然後判斷一下此時是否l‘<=l就行了。
之後就繼續增大w,重復上面的操作...最後維護一下答案就行了。
我的暴力代碼..
#include <bits/stdc++.h> using namespace std; typedef long long ll; ll a,b,c; vector <ll> v1,v2,v3; bool check(ll l,ll s){ ll r=s/l; for(auto width:v2){ ll len = c/width; if(width<=l && len<=r) return true; } return false; } int main(){ cin>>a>>b; ll s=a+b; c=a; for(ll i=1;i*i<=s;i++) if(s%i==0) v1.push_back(i); for(ll i=1;i*i<=c;i++) if(c%i==0) v2.push_back(i); ll ans; for(int i=v1.size()-1;i>=0;i--){ ll l=v1[i],r=s/v1[i]; if(check(l,s)){ ans = (v1[i]+s/v1[i])*2; break ; } } c=b;v2.clear(); for(ll i=1;i*i<=c;i++) if(c%i==0) v2.push_back(i); for(int i=v1.size()-1;i>=0;i--){ ll l=v1[i],r=s/v1[i]; if(check(l,s)){ ans = min((v1[i]+s/v1[i])*2,ans); break ; } } printf("%I64d",ans); return 0; }View Code
Codeforces Round #506 (Div. 3) 題解