zoukankan      html  css  js  c++  java
  • Educational Codeforces Round 83 总结

    A

    #include <bits/stdc++.h>
    using namespace std;
    
    int t,n,m;
    
    signed main() {
        ios::sync_with_stdio(false);
        cin>>t;
        while(t--) {
            cin>>n>>m;
            if(n%m==0) puts("YES");
            else puts("NO");
        }
    }
    
    

    B

    给定序列 (a),构造一个解,将它重新排序后,称为一个新的序列,使得 (j-i eq a_j-a_i)

    排序后再翻转

    #include <bits/stdc++.h>
    using namespace std;
    
    int t,n,a[105];
    
    signed main() {
        ios::sync_with_stdio(false);
        cin>>t;
        while(t--) {
            cin>>n;
            for(int i=1;i<=n;i++) cin>>a[i];
            sort(a+1,a+n+1);
            reverse(a+1,a+n+1);
            for(int i=1;i<=n;i++) cout<<a[i]<<" ";
            cout<<endl;
        }
    }
    
    

    C

    能否对一个初态都为 (0) 数组执行任意次操作,使他变成目标数组。第 (i) 次操作可以放弃,或者给某个元素加上 (k^i)

    (k=1) 的特判掉,剩下的相当于一个进制分解判重

    #include <bits/stdc++.h>
    using namespace std;
    
    #define int long long
    const int N = 100;
    const int lim = 1e16;
    
    int t,n,k,a[N],u[N];
    
    signed main() {
        ios::sync_with_stdio(false);
        cin>>t;
        while(t--) {
            cin>>n>>k;
            for(int i=1;i<=n;i++) cin>>a[i];
            if(k==1) {
                puts("YES");
                continue;
            }
            memset(u,0,sizeof u);
            int fg=0;
            for(int i=1;i<=n;i++) {
                for(int j=0;j<=66;j++) {
                    if(a[i]%k==1) {
                        ++u[j];
                    }
                    else if(a[i]%k>1) {
                        puts("NO");
                        goto AERR;
                    }
                    a[i]/=k;
                }
            }
    
            for(int i=0;i<=66;i++) fg=max(fg,u[i]);
            if(fg>1) puts("NO");
            else puts("YES");
            AERR:cout<<"";
        }
    }
    
    

    D

    求长度为 (n) 的序列 (a) 的个数:(a_i in [1,m]),存在且仅存在一对相同元素,存在 (p) 使得 (a[1...p]) 严格单增,(a[p...n]) 严格单调递减

    #include <bits/stdc++.h>
    using namespace std;
    
    #define int long long
    const int mod = 998244353;
    
    int qpow(int p,int q) {
        return (q&1?p:1) * (q?qpow(p*p%mod,q/2):1) % mod;
    }
    
    int frac(int p) {
        int res = 1;
        for(int i=1;i<=p;i++) res *= i, res %= mod;
        return res;
    }
    
    int inv(int p) {
        return qpow(p,mod-2);
    }
    
    signed main() {
        int n,m;
        cin>>n>>m;
        int ans=frac(m)*inv(frac(n-1))%mod*inv(frac(m-n+1))%mod;
        ans=ans*(n-2)%mod*qpow(2,n-3)%mod;
        cout<<ans;
    }
    
    

    E

    给定一个长度为 (n leq 500) 的数组 (a),元素均 (leq 1000),每次你可以找到 (i) 使得 (a[i]=a[i+1]),将它们替换成一个数 (a_i+1),求剩余数组长度的最小值

    #include <bits/stdc++.h>
    using namespace std;
    
    #define int long long
    const int N = 505;
    
    int n,a[N],f[N][N],g[N][N];
    
    signed main() {
        ios::sync_with_stdio(false);
        cin>>n;
        for(int i=1;i<=n;i++) cin>>a[i];
        for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) f[i][j]=-1;
        for(int i=1;i<=n;i++) f[i][i]=a[i];
        for(int l=1;l<n;l++) {
            for(int i=1;i+l<=n;i++) {
                int j=i+l;
                for(int k=i;k<j;k++) {
                    if(f[i][k]>0 && f[k+1][j]>0 && f[i][k]==f[k+1][j]) {
                        f[i][j]=f[i][k]+1;
                    }
                }
            }
        }
        for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) {
            if(f[i][j]==-1) g[i][j]=1e9;
            else g[i][j]=1;
        }
        for(int l=1;l<n;l++) {
            for(int i=1;i+l<=n;i++) {
                int j=i+l;
                for(int k=i;k<j;k++) {
                    g[i][j]=min(g[i][j],g[i][k]+g[k+1][j]);
                }
            }
        }
        cout<<g[1][n];
    }
    
    

    F

    (n) 个数,甲乙两人轮流操作,甲先手,每次操作有三个选项

    • 将一个 (>0) 的数 (-x)
    • 将一个 (>0) 的数 (-y)
    • 将一个 (>0) 的数 (-z)

    如果操作后这个数 (<0) 则自动变为 (0)

    对于一个数,如果上次对这个数操作是第二种,那么这次就不能操作第二种,如果上次对这个数操作是第三种,那么这次就不能操作第三种

    不能操作的人输,问甲先手,第一步有多少种办法使得自己必胜

    Solution

    首先可以将各个 (a_i) 分开来考虑,最后将结果异或起来就是局面的 SG 值

    (SG(x,c)) 表示在这个数为 (x),上次操作为 (c) 时的 SG 值,那么转移很显然是

    [SG(i,0)= ext{mex} { SG(i-x,0),SG(i-y,1),SG(i-z,2) } \ SG(i,1)= ext{mex} { SG(i-x,0),SG(i-z,2) } \ SG(i,2)= ext{mex} { SG(i-x,0),SG(i-y,1) } ]

    由于 (x,y,z) 很小,所以 (SG) 函数一定有一个很小的循环节

    #include <bits/stdc++.h>
    
    using namespace std;
    #define int long long
    
    int mex(set<int> s) {
        for(int i=0;i<=4;i++) if(s.find(i)==s.end()) return i;
    }
    
    int x,y,z;
    
    namespace sg {
        int sg[105][4];
        int I,J;
        int getsg(int t,int c) {
            if(t<J) return sg[t][c];
            return sg[J+(t-J)%(I-J)][c];
        }
        void clear() {
            I=0; J=0;
            memset(sg,0,sizeof sg);
        }
        void calc(int ai) {
            for(int i=1;;i++) {
                set<int> s;
                s.insert(sg[max(0ll,i-x)][0]);
                s.insert(sg[max(0ll,i-y)][1]);
                s.insert(sg[max(0ll,i-z)][2]);
                sg[i][0]=mex(s);
                s.clear();
                s.insert(sg[max(0ll,i-x)][0]);
                s.insert(sg[max(0ll,i-z)][2]);
                sg[i][1]=mex(s);
                s.clear();
                s.insert(sg[max(0ll,i-x)][0]);
                s.insert(sg[max(0ll,i-y)][1]);
                sg[i][2]=mex(s);
                for(int j=4;j<i-4;j++) {
                    int fg=1;
                    for(int k=0;k<=4;k++) {
                        for(int u=0;u<3;u++) {
                            if(sg[j-k][u]!=sg[i-k][u]) fg=0;
                        }
                    }
                    if(fg) {
                        I=i;
                        J=j;
                        return;
                    }
                }
            }
        }
    }
    
    int t,n,a[300005],ssg[300005][3],osg[300005];
    
    signed main() {
        ios::sync_with_stdio(false);
        cin>>t;
        while(t--) {
            cin>>n>>x>>y>>z;
            for(int i=1;i<=n;i++) cin>>a[i];
            sg::clear();
            sg::calc(0);
            int sum=0;
            for(int i=1;i<=n;i++) {
                osg[i]=sg::getsg(a[i],0);
                sum^=osg[i];
                ssg[i][0]=sg::getsg(max(0ll,a[i]-x),0);
                ssg[i][1]=sg::getsg(max(0ll,a[i]-y),1);
                ssg[i][2]=sg::getsg(max(0ll,a[i]-z),2);
            }
            int ans=0;
            for(int i=1;i<=n;i++) {
                if((sum^osg[i]^ssg[i][0])==0) ++ans;
                if((sum^osg[i]^ssg[i][1])==0) ++ans;
                if((sum^osg[i]^ssg[i][2])==0) ++ans;
            }
            cout<<ans<<endl;
        }
    }
    
    

    G

    给定一个字符串集合 (S),需要计算打 (S) 中所有字符串花费的时间总和

    打一个字符串的步骤如下:从一个空串开始;如果当前的字符串是 (t),你可以末尾拼接任意一个小写字母,花费 (1s)

    你可以使用自动补全功能,设当前字符串是 (t),此时所有 (sin S) 会按照字典序展现出来,自动补全到第 (i) 个串需要 (is)

    #include <bits/stdc++.h>
    using namespace std;
    
    const int inf=1e9;
    const int N=1e+6+5;
    
    struct node {
        char c;
        int nxt;
        bool operator < (const node &b) const {
            return c<b.c;
        }
    };
    int n,m,q[N],tar[N],ans[N];
    
    vector <node> g[N];
    
    int dfs(int u,int c) {
        int rk=0;
        if(tar[u]) ans[u]=min(ans[u],c), ++rk;
        for(int i=0;i<g[u].size();i++) {
            int v=g[u][i].nxt;
            ans[v]=ans[u]+1;
            rk+=dfs(v,min(ans[v],c)+rk);
        }
        return rk;
    }
    
    signed main() {
        ios::sync_with_stdio(false);
        cin>>n;
        for(int i=1;i<=n;i++) {
            int t;
            char c;
            cin>>t>>c;
            g[t].push_back({c,i});
        }
        for(int i=0;i<n;i++) sort(g[i].begin(),g[i].end());
        cin>>m;
        for(int i=1;i<=m;i++) {
            cin>>q[i];
            tar[q[i]]=1;
        }
        dfs(0,inf);
        for(int i=1;i<=m;i++) cout<<ans[q[i]]<<" ";
    }
    
    
  • 相关阅读:
    前端开发——HTML学习笔记
    前端开发——HTML学习笔记
    前端开发——HTML学习笔记
    日记2018/1/4
    物联网概念
    安卓常见英文缩写的全拼
    快速排序和计数排序API
    Hash表API
    栈/队列API(push和pop)
    链表API实现(插入,删除,查找)
  • 原文地址:https://www.cnblogs.com/mollnn/p/12531167.html
Copyright © 2011-2022 走看看