zoukankan      html  css  js  c++  java
  • Codeforces Round #486 (Div. 3) A-F题解

    A.题意:100个数字,大小100,问可否从中选出k个不同数字,输出位置
    思路:map.count
    代码:

    #include <bits/stdc++.h>
    using namespace std;
    #define ll long long
    #define forn(i,n) for(int i=0;i<n;i++)
    #define for1(i,n) for(int i=1;i<=n;i++)
    #define IO ios::sync_with_stdio(false);cin.tie(0)
    const int inf = 0x3f3f3f3f;
    const ll INF = 0x3f3f3f3f3f3f3f3f;
    
    int main(){
        IO;
        int n,k;cin>>n>>k;
        vector<int> a;
        map<int,int>mp;
        forn(i,n){
            int x;cin>>x;
            if(!mp[x]) a.push_back(i+1);
            mp[x]++;
        }
        if(a.size()>=k){
            cout<<"YES"<<'
    ';
            forn(i,k) cout<<a[i]<<' ';
        } else cout<<"NO"<<'
    ';
        return 0;
    }
    

    B.题意:给100个长度为100的字符串,排序使得前面的每一个字符串前面的字符串为他的的子串。
    思路:暴力就可以了,不暴力可以dp+kmp做,substr可以减少代码量,用法为string.(起始位置,长度)
    代码:

    #include <bits/stdc++.h>
    using namespace std;
    #define ll long long
    #define forn(i,n) for(int i=0;i<n;i++)
    #define for1(i,n) for(int i=1;i<=n;i++)
    #define IO ios::sync_with_stdio(false);cin.tie(0)
    const int inf = 0x3f3f3f3f;
    const ll INF = 0x3f3f3f3f3f3f3f3f;
    
    vector<string>s[100];
    map<int,pair<int,int> >mp;
    
    int main(){
        IO;
        int n;cin>>n;
        forn(i,n){
            int m;cin>>m;
            vector<int>a(m);
            int sum = 0;
            forn(j,m){
                cin>>a[j];
                sum+=a[j];
            }
            forn(j,m)if(mp.count(sum-a[j])){
                cout<<"YES"<<'
    ';
                auto ans = mp[sum-a[j]];
                cout<< ans.first+1<<' '<<ans.second+1<<'
    ';
                cout<<i+1<<' '<<j+1<<'
    ';
                return 0;
            }
            forn(j,m)if(!mp.count(sum-a[j]))mp[sum-a[j]] = {i,j};
        }
        cout<<"NO"<<'
    ';
        return 0;
    }
    

    C.题意:2e5个数组,共最多2e5个数,能否删除某两个数组的一个数字,使得这两个数组的sum值相同。
    思路:map存,出现答案return
    代码:

    #include <bits/stdc++.h>
    using namespace std;
    #define ll long long
    #define forn(i,n) for(int i=0;i<n;i++)
    #define for1(i,n) for(int i=1;i<=n;i++)
    #define IO ios::sync_with_stdio(false);cin.tie(0)
    const int inf = 0x3f3f3f3f;
    const ll INF = 0x3f3f3f3f3f3f3f3f;
    
    vector<string>s[100];
    map<int,pair<int,int> >mp;
    
    int main(){
        IO;
        int n;cin>>n;
        forn(i,n){
            int m;cin>>m;
            vector<int>a(m);
            int sum = 0;
            forn(j,m){
                cin>>a[j];
                sum+=a[j];
            }
            forn(j,m)if(mp.count(sum-a[j])){
                cout<<"YES"<<'
    ';
                auto ans = mp[sum-a[j]];
                cout<< ans.first+1<<' '<<ans.second+1<<'
    ';
                cout<<i+1<<' '<<j+1<<'
    ';
                return 0;
            }
            forn(j,m)if(!mp.count(sum-a[j]))mp[sum-a[j]] = {i,j};
        }
        cout<<"NO"<<'
    ';
        return 0;
    }
    

    D.
    题意:2e5个数,问最多取多少个数字使得各个数字两两差为2的幂。
    思路:取一个数,它右边最多取一个,左边最多取一个。假设取了两个那么必然和本数差2^k和2的幂次方,可以看为二进制的两个不同位置的1,那么这两个差肯定是多个1,除了最小那两个以外。当我们考虑最小的两个会发现,左边取不了。所以最多三个,知道这个定理之后就可以map记录然后枚举。
    代码:

    #include <bits/stdc++.h>
    using namespace std;
    #define ll long long
    #define forn(i,n) for(int i=0;i<n;i++)
    #define for1(i,n) for(int i=1;i<=n;i++)
    #define IO ios::sync_with_stdio(false);cin.tie(0)
    
    map<ll,int>mp;
    int main(){ 
        IO;
        int n;cin>>n;vector<ll>a(n);forn(i,n){
            int x; cin>>x;a[i] = x;
            mp[x] = 1;
        }
        forn(j,n){
            forn(i,32){
                ll x = 1ll<<i;
                //if(a[j]==5&&i==1) cerr<<a[j]<<' '<<x<<' '<<a[j]+x<<' '<<a[j]+x<<'
    ';
                if(mp.count(x+a[j])&&mp.count(a[j]-x)){
                    cout<<3<<'
    ';
                    cout<<a[j]-x<<' '<<a[j]<<' '<<a[j]+x<<'
    ';
                    return 0;
                }
            }
        }
        forn(j,n){
            forn(i,32){
                ll x = 1ll<<i;
                if(mp.count(x+a[j])){
                    cout<<2<<'
    ';
                    cout<<a[j]+x<<' '<<a[j]<<'
    ';
                    return 0;
                }
                if(mp.count(a[j]-x)){
                    cout<<2<<'
    ';
                    cout<<a[j]-x<<' '<<a[j]<<'
    ';
                    return 0;
                }
            }
        }
        cout<<1<<'
    '<<a[0]<<'
    ';
        return 0;
    }
    

    E.
    题意:给一个数字经过一些操作使得它可以被25整除,每次操作可以使相邻两数直接交换位置,不能有前导0,求最小操作次数。
    思路:显然末尾只要有00,50,25,75就可以了,那么分类讨论,先移动最近的0或5,在找最近的另一个数字。比如50267,要考虑前导0,那么我们最后判断有前导0的情况找按顺序找第一个非0的数。加上去取min即可。
    代码:

    #include <bits/stdc++.h>
    using namespace std;
    #define ll long long
    #define forn(i,n) for(int i=0;i<n;i++)
    #define for1(i,n) for(int i=1;i<=n;i++)
    #define IO ios::sync_with_stdio(false);cin.tie(0)
    const int inf = 0x3f3f3f3f;
    int main(){
        IO;
        string s,m;cin>>s;
        m = s;
        int ans = inf,res = inf,pos = 0;
        bool ok1 = 0,ok2 = 0;
        for(int i = m.size()-1;i>=0;i--){
            if(m[i]=='5'){
                ok1 = 1;
                res = 0;
                res+=m.size()-i-1;
                pos = i;
                break;
            }
        }
        if(res!=inf){
            for(int i = pos+1;i<m.size();i++) swap(m[i],m[i-1]);
            for(int i = m.size()-2;i>=0;i--){
                if(m[i]=='2'||m[i]=='7'){
                    ok2 = 1;
                    res+=m.size()-i-2;
                    pos = i;
                    break;
                }
            }
            for(int i = pos+1;i<m.size()-1;i++)swap(m[i],m[i-1]);
            if(m[0]=='0'){
                for(int i = 0;i<m.size()-2;i++){
                    if(m[i]!='0'){
                        res+=i;
                        m[0]='#';
                        break;
                    }
                }
            }
        }
        if(m[0]!='0'&&ok1&&ok2) ans = res;
        res = inf,m = s,ok1=ok2 = 0;
        for(int i = m.size()-1;i>=0;i--){
            if(s[i]=='0'){
                ok1 = 1;
                res = 0;
                res+=m.size()-i-1;
                pos = i;
                break;
            }
        }
        if(res!=inf){
            for(int i = pos+1;i<m.size();i++) swap(m[i],m[i-1]);
            for(int i = m.size()-2;i>=0;i--){
                if(m[i]=='5'||m[i]=='0'){
                    ok2 = 1;
                    res+=m.size()-i-2;
                    pos = i;
                    break;
                }
            }
            for(int i = pos+1;i<m.size()-1;i++)swap(m[i],m[i-1]);
            if(m[0]=='0'){
                for(int i = 0;i<m.size()-2;i++){
                    if(m[i]!='0'){
                        res+=i;
                        m[0]='#';
                        break;
                    }
                }
            }
        }
        if(m[0]!='0'&&ok1&&ok2) ans = min(ans,res);
        if(ans!=inf) cout<<ans<<'
    ';
        else cout<<-1<<'
    ';
        return 0;
    }
    

    F.
    题意:一条路从1点走到a点,一次只移动1格。现在有n个区间有雨,你在下雨区间必须打伞。现在上帝给你在m个点都放了伞,每把伞有它的放的位置pi和你的坏感度wi。当你拿一把伞走了1个距离,那么你的心情-wi。你可以随时扔掉伞,如果pi有伞你可以捡伞换伞。问心情最少-多少。
    思路:dpij i表示走到第几个点,j表示此时手上用第j个雨伞
    每次可以转移这三种:

    1. i的时候没有雨扔掉伞dpi-1j转移到dpi0
    2. 继续打伞dpi-1j转移到dpij
    3. i-1处有新伞换伞dpi-1j转移到dpia[i-1](a表示伞)
      代码:
    #include <bits/stdc++.h>
    using namespace std;
    #define ll long long
    #define forn(i,n) for(int i=0;i<n;i++)
    #define for1(i,n) for(int i=1;i<=n;i++)
    #define IO ios::sync_with_stdio(false);cin.tie(0)
    const int maxn = 2005;
    const int inf = 0x3f3f3f3f;
    bool vis[maxn];
    int p[maxn],dp[maxn][maxn];
    
    int main(){ 
        IO;
        int e,n,m;cin>>e>>n>>m;
        memset(dp,inf,sizeof(dp));
        forn(i,n){
            int l,r;cin>>l>>r;
            for(int i = l+1;i<=r;i++) vis[i] = 1;
        }
        vector<int>w(m+1);
        w[0] = inf;
        for1(i,m){
            int x,y;cin>>x>>y; 
            w[i] = y; 
            if(w[p[x]]>y) p[x] = i;
        }
        dp[0][0] = 0;
        for1(i,e){
            for(int j = 0;j<=m;j++){
                if(!vis[i])dp[i][0] = min(dp[i][0],dp[i-1][j]);
                if(j) dp[i][j] = min(dp[i][j],dp[i-1][j]+w[j]);
                if(p[i-1]) dp[i][p[i-1]] = min(dp[i][p[i-1]],dp[i-1][j]+w[p[i-1]]);
            }
        }
        int ans = inf;
        forn(i,m+1) ans = min(ans,dp[e][i]);
        if(ans==inf) cout<<-1<<'
    ';
        else cout<<ans<<'
    ';
        return 0; 
    }
    
  • 相关阅读:
    移动Oracle数据库表空间文件。
    Web页面嵌入复杂WinForm控件权限问题
    关于bleand2000下面oracle服务器优化
    祝大家新年快乐!
    CentOS安装配置MongoDB及PHP MongoDB 扩展安装配置 新风宇宙
    FastDFS介绍和配置过程 新风宇宙
    ubuntu下安装redisserver和phpredis 新风宇宙
    PHP安装fastDFS扩展 新风宇宙
    用socket发送流数据示用 php://input? 接受post数据(可实现php和c/c++数据通讯) 新风宇宙
    linux操作系统下c语言编程入门 新风宇宙
  • 原文地址:https://www.cnblogs.com/AlexPanda/p/12520300.html
Copyright © 2011-2022 走看看