zoukankan      html  css  js  c++  java
  • 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>
    using namespace 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;
    }
    View Code

    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];
    int 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;
    }
    View Code

    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 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
  • 相关阅读:
    ubuntu安装redis
    ubuntu安装mongodb
    IO-MYSQL的理解
    HTTP协议理解
    linux面试
    mysql引擎事物支持
    ubuntu安装scrapy方法
    mysql关系型和非关系型区别
    mysql引擎
    vue优势
  • 原文地址:https://www.cnblogs.com/heyuhhh/p/10294095.html
Copyright © 2011-2022 走看看