zoukankan      html  css  js  c++  java
  • Codeforces Round #636 (Div. 3)题解

    A. 给你一个n,解方程,(1+2+4+...+2^(k-1))*x=n,保证k>1。

      枚举k,可以整除时输出一个数。

    #include<bits/stdc++.h>
    
    #define all(x) x.begin(),x.end()
    #define fi first
    #define sd second
    #define lson (nd<<1)
    #define rson (nd+nd+1)
    #define PB push_back
    #define mid (l+r>>1)
    #define MP make_pair
    #define SZ(x) (int)x.size()
    
    using namespace std;
    
    typedef long long LL;
    
    typedef vector<int> VI;
    
    typedef pair<int,int> PII;
    
    inline int read(){
        int res=0, f=1;char ch=getchar();
        while(ch<'0'|ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){res=res*10+ch-'0';ch=getchar();}
        return res*f;
    }
    
    const int MAXN = 200'005;
    
    const int MOD = 1000000007;
    
    void addmod(int& a, int b){a+=b;if(a>=MOD)a-=MOD;}
    int mulmod(int a, int b){return 1ll*a*b%MOD;}
    
    template<typename T>
    void chmin(T& a, T b){if(a>b)a=b;}
    
    template<typename T>
    void chmax(T& a, T b){if(b>a)a=b;}
    
    void solve(){
        int n=read();
        for(int i=2;i<=30;++i){
            int v=(1<<i)-1;
            if(n%v==0){
                cout<<n/v<<endl;
                return;
            }
        }
    }
    
    int main(){
        int t=read();
        while(t--){
            solve();
        }
    
        return 0;
    }
    View Code

    B. 给一个偶数n,构造一个数组,前面都是偶数,后面都是奇数,且互不相同。且前面n/2个数的和与后面n/2个数的和相等。

      首先n/2不是偶数直接输出“NO”,然后就随便搞搞。

    #include<bits/stdc++.h>
    
    #define all(x) x.begin(),x.end()
    #define fi first
    #define sd second
    #define lson (nd<<1)
    #define rson (nd+nd+1)
    #define PB push_back
    #define mid (l+r>>1)
    #define MP make_pair
    #define SZ(x) (int)x.size()
    
    using namespace std;
    
    typedef long long LL;
    
    typedef vector<int> VI;
    
    typedef pair<int,int> PII;
    
    inline int read(){
        int res=0, f=1;char ch=getchar();
        while(ch<'0'|ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){res=res*10+ch-'0';ch=getchar();}
        return res*f;
    }
    
    const int MAXN = 200'005;
    
    const int MOD = 1000000007;
    
    void addmod(int& a, int b){a+=b;if(a>=MOD)a-=MOD;}
    int mulmod(int a, int b){return 1ll*a*b%MOD;}
    
    template<typename T>
    void chmin(T& a, T b){if(a>b)a=b;}
    
    template<typename T>
    void chmax(T& a, T b){if(b>a)a=b;}
    
    
    void solve(){
        int n=read();
        if((n/2)&1){
            cout<<"NO"<<endl;
        }else{
            cout<<"YES"<<endl;
            for(int i=1;i<=n/2;++i){
                cout<<2*i<<" ";
            }
            for(int i=1;i<=n/2-1;++i){
                cout<<2*i-1<<" ";
            }
            cout<<3*n/2-1<<endl;
        }
    }
    
    int main(){
        int t=read();
        while(t--){
            solve();
        }
    
        return 0;
    }
    View Code

    C. 给一个长度为n的数组,里面没有0。求一个正负交替的子序列,其和最大。

      首先可以发现,一段连续的正数和负数只能选一个,直接贪心选最大。

    #include<bits/stdc++.h>
    
    #define all(x) x.begin(),x.end()
    #define fi first
    #define sd second
    #define lson (nd<<1)
    #define rson (nd+nd+1)
    #define PB push_back
    #define mid (l+r>>1)
    #define MP make_pair
    #define SZ(x) (int)x.size()
    
    using namespace std;
    
    typedef long long LL;
    
    typedef vector<int> VI;
    
    typedef pair<int,int> PII;
    
    inline LL read(){
        LL res=0, f=1;char ch=getchar();
        while(ch<'0'|ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){res=res*10+ch-'0';ch=getchar();}
        return res*f;
    }
    
    const int MAXN = 200'005;
    
    const int MOD = 1000000007;
    
    void addmod(int& a, int b){a+=b;if(a>=MOD)a-=MOD;}
    int mulmod(int a, int b){return 1ll*a*b%MOD;}
    
    template<typename T>
    void chmin(T& a, T b){if(a>b)a=b;}
    
    template<typename T>
    void chmax(T& a, T b){if(b>a)a=b;}
    
    
    void solve(){
        LL n=read();
        vector<LL> a(n);
        vector<LL> b;
        for(int i=0;i<n;++i){
            a[i]=read();
            if(i!=0){
                if(b.back()*a[i]>0){
                    b.back()=max(b.back(),a[i]);
                }else{
                    b.PB(a[i]);
                }
            }else{
                b.PB(a[0]);
            }
        }
        cout<<accumulate(all(b),0ll)<<endl;
    }
    
    int main(){
        LL t=read();
        while(t--){
            solve();
        }
    
        return 0;
    }
    View Code

    D. 给你n个数的数组,n为偶数。每一个数都不超过k,修改之后的值也不能超过k。现在求最小的修改次数,使得a[i]+a[n-i+1]=const。

      考虑一下右边的这个常数,我们会发现,对于每一个二元组,是可以O(1)得到某一个常数对应的修改次数的。直接差分,O(n)做完。

    #include<bits/stdc++.h>
    
    #define all(x) x.begin(),x.end()
    #define fi first
    #define sd second
    #define lson (nd<<1)
    #define rson (nd+nd+1)
    #define PB push_back
    #define mid (l+r>>1)
    #define MP make_pair
    #define SZ(x) (int)x.size()
    
    using namespace std;
    
    typedef long long LL;
    
    typedef vector<int> VI;
    
    typedef pair<int,int> PII;
    
    inline int read(){
        int res=0, f=1;char ch=getchar();
        while(ch<'0'|ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){res=res*10+ch-'0';ch=getchar();}
        return res*f;
    }
    
    const int MAXN = 200'005;
    
    const int MOD = 1000000007;
    
    void addmod(int& a, int b){a+=b;if(a>=MOD)a-=MOD;}
    int mulmod(int a, int b){return 1ll*a*b%MOD;}
    
    template<typename T>
    void chmin(T& a, T b){if(a>b)a=b;}
    
    template<typename T>
    void chmax(T& a, T b){if(b>a)a=b;}
    
    void solve(){
        int n=read(),k=read();
        vector<int> a(2*k+5,0);
        vector<int> num(n+1);
        for(int i=1;i<=n;++i)num[i]=read();
    
        for(int i=1;i<=n/2;++i){
            int x=num[i]+num[n-i+1];
    
            int l1=x-max(num[i],num[n-i+1])+1;
            int r1=x;
    
            int l2=x+1;
            int r2=x+k-min(num[i],num[n-i+1])+1;
    
            int l3=2;
            int r3=max(l3,l1);
    
            int l4=r2;
            int r4=2*k+1;
    
            a[l1]+=1;
            a[r1]-=1;
    
            a[l2]+=1;
            a[r2]-=1;
    
            a[l3]+=2;
            a[r3]-=2;
    
            a[l4]+=2;
            a[r4]-=2;
        }
    
        for(int i=1;i<=2*k;++i)a[i]=(a[i-1]+a[i]);
    
        cout<<*min_element(a.begin()+2,a.begin()+2*k+1)<<endl;
    
    }
    
    
    int main(){
        int t=read();
        while(t--){
            solve();
        }
        return 0;
    }
    
    /*
    1
    2 1
    1 1
    */
    View Code

    E. 给你一个n个点,m条边的图,和m个值,要求给边分配权重,使得从a->b->c,权重和最小。

      首先考虑一种简单的情况,如果只有两个点。那么毫无疑问,我们直接bfs出最短路,贪心选择最小的边即可。现在变成三个点,其实也差不多,我们要走的路径,其实都是“一”,"Y","V"字型的。即,有一些边我们是要走两次的,肯定要选权值最小的几条边,其他的就贪心的去选就行了。现在如果想去找a->b和c->b经过了哪些点是行不通的,无论是bfs还是dfs都跑不通。原因是最短路可能不止一条,这直接导致两条路径不重合,代价变大(蒟蒻哭泣)。正确的做法是,枚举一个点,得到这个点与a,b,c,三个点的距离。然后到b的距离安排上最小的一些边权(因为要算两次),然后贪心的去选取其他的边权。正确性也是显然的,首先,两条最短路上的点一定比非路径上的点优(很显然),其次是分叉点一定比其他点优。

    #include<bits/stdc++.h>
    
    #define all(x) x.begin(),x.end()
    #define fi first
    #define sd second
    #define lson (nd<<1)
    #define rson (nd+nd+1)
    #define PB push_back
    #define mid (l+r>>1)
    #define MP make_pair
    #define SZ(x) (int)x.size()
    
    using namespace std;
    
    typedef long long LL;
    
    typedef vector<int> VI;
    
    typedef pair<int,int> PII;
    
    inline int read(){
        int res=0, f=1;char ch=getchar();
        while(ch<'0'|ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){res=res*10+ch-'0';ch=getchar();}
        return res*f;
    }
    
    const int MAXN = 200'005;
    
    const int MOD = 1000000007;
    
    void addmod(int& a, int b){a+=b;if(a>=MOD)a-=MOD;}
    int mulmod(int a, int b){return 1ll*a*b%MOD;}
    
    template<typename T>
    void chmin(T& a, T b){if(a>b)a=b;}
    
    template<typename T>
    void chmax(T& a, T b){if(b>a)a=b;}
    
    void solve(){
        int n=read(),m=read(),a=read(),b=read(),c=read();
        --a;--b;--c;
        vector<vector<int>> G(n,vector<int>());
    
        vector<int> val(m);
        for(int i=0;i<m;++i)val[i]=read();
        sort(all(val));
        vector<LL> sum(m+1,0);
        for(int i=1;i<=m;++i)sum[i]=sum[i-1]+val[i-1];
    
        for(int i=1;i<=m;++i){
            int u=read();int v=read();
            --u;--v;
            G[u].PB(v);G[v].PB(u);
        }
    
        LL ans=1e18;
    
        auto bfs=[&](int x){
            vector<int> d(n,-1);
            queue<int> q;
            q.push(x);
            d[x]=0;
    
            while(!q.empty()){
                int u=q.front();
                q.pop();
                for(auto it:G[u]){
                    if(d[it]!=-1)continue;
                    else{
                        d[it]=d[u]+1;
                        q.push(it);
                    }
                }
            }
    
            return d;
        };
    
        auto da=bfs(a),db=bfs(b),dc=bfs(c);
    
        for(int i=0;i<n;++i){
            int dx=da[i],dy=db[i],dz=dc[i];
            if(dx+dy+dz>m)continue;
            else ans=min(ans,sum[dy]+sum[dx+dy+dz]);
        }
    
        cout<<ans<<endl;
    }
    
    int main(){
        int t=read();
        while(t--){
            solve();
        }
    
        return 0;
    }
    /*
    1
    4 4 1 3 4
    1 2 3 4
    1 2
    2 3
    3 4
    1 4
    
    4
    */
    View Code

    F. 现在有一个排列,长度为n。现在的情况是,给从右端点(r=2...n),左端点随便选(l<r),的n-1个区间段,但是这个区间段是排序之后的。n-1个区间段是随机给的,现在要复原这个排列。

      枚举第一个元素,考虑对所有的区间段删掉这个元素,那么一定只有一个区间段长度为1(不是则这个第一个值不合法)。原因很显然,因为其他的删不到第一个元素。现在变成了一个子问题了,只不过第一个值变成了那个长度为1的子段的值。

      这样就能得到一些解,但是很神奇的是,这这是一个必要条件,不一定是充分的。所以我们还需要要验证这n-1个子段能不能生成。

    #include<bits/stdc++.h>
    
    #define all(x) x.begin(),x.end()
    #define fi first
    #define sd second
    #define lson (nd<<1)
    #define rson (nd+nd+1)
    #define PB push_back
    #define mid (l+r>>1)
    #define MP make_pair
    #define SZ(x) (int)x.size()
    
    using namespace std;
    
    typedef long long LL;
    
    typedef vector<int> VI;
    
    typedef pair<int,int> PII;
    
    inline int read(){
        int res=0, f=1;char ch=getchar();
        while(ch<'0'|ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){res=res*10+ch-'0';ch=getchar();}
        return res*f;
    }
    
    const int MAXN = 200'005;
    
    const int MOD = 1000000007;
    
    void addmod(int& a, int b){a+=b;if(a>=MOD)a-=MOD;}
    int mulmod(int a, int b){return 1ll*a*b%MOD;}
    
    template<typename T>
    void chmin(T& a, T b){if(a>b)a=b;}
    
    template<typename T>
    void chmax(T& a, T b){if(b>a)a=b;}
    
    void solve(){
        int n=read();
    
        vector<set<int>> a(n-1);
        for(int i=0;i<n-1;++i){
            int k=read();
            for(int j=0;j<k;++j){
                a[i].insert(read());
            }
        }
    
        for(int fst=1;fst<=n;++fst){
            auto b=a;
    
            int ok=1;
    
            vector<int> ans;
            ans.PB(fst);
    
            for(int i=0;i<n-1;++i){
                if(SZ(b[i])>0&&b[i].count(fst)){
                    b[i].erase(b[i].find(fst));
                }
            }
    
            for(int iter=1;iter<n;++iter){
                int cnt=0;
                int nxt=-1;
    
                for(int i=0;i<n-1;++i){
                    if(SZ(b[i])==1){
                        ++cnt;
                        nxt=*b[i].begin();
                        b[i].clear();
                    }
                }
    
                if(cnt>1||cnt==0){
                    ok=0;break;
                }
    
                ans.PB(nxt);
    
                for(int i=0;i<n-1;++i){
                    if(SZ(b[i])>0&&b[i].count(nxt)){
                        b[i].erase(b[i].find(nxt));
                    }
                }
            }
    
            if(!ok)continue;
            else{
                for(int i=0;i<n-1;++i){
                    int okok=0;
                    for(int j=0;j<n;++j){
                        set<int> s;s.insert(ans[j]);
                        for(int k=j+1;k<n;++k){
                            s.insert(ans[k]);
                            if(a[i]==s){
                                okok=1;
                                break;
                            }
                        }
                    }
    
                    if(!okok){
                        ok=0;
                        break;
                    }
                }
    
                if(ok){
                    for(int i=0;i<n;++i)cout<<ans[i]<<" 
    "[i==n-1];
                    return;
                }
            }
        }
    }
    
    
    int main(){
        int t=read();
        while(t--){
            solve();
        }
    
        return 0;
    }
    View Code

      

  • 相关阅读:
    页面刷新后,页面重新棍回到原来的位置;如何在回发后返回客户端时仍然保持滚动条原来的位置
    asp.net查询数据库时提示使用的sql server版本不支持数据类型date
    GridView导出Excel研究
    asp.net GridView 时间格式化 设置 短日期格式 去掉0!
    存储过车如果没有参数,不要加后面的括号,否则报错
    只能在执行 Render() 的过程中调用 RegisterForEventValidation(RegisterForEventValidation can only be called during Render(); )
    OpenCV下的图片缩放(相关版本: OpenCV 2.1)
    Oracle Spatial 翻译第一漳
    矩阵基本运算的实现(standard C++Version)
    Oracle Spatial 翻译部分的原文
  • 原文地址:https://www.cnblogs.com/JohnRan/p/12755300.html
Copyright © 2011-2022 走看看