• 《Codeforces Round #738 (Div. 2)》


    A:很显然对于每个bit位,只要存在一个0,最终都能通过很多次操作后全部变成0.统计全部为1的位数即可。

    // Author: levil
    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    typedef pair<int,int> pii;
    const int N = 2e5 + 5;
    const int M = 5e5 + 5;
    const LL Mod = 1e9 + 7;
    #define pi acos(-1)
    #define INF 1e16
    #define dbg(ax) cout << "now this num is " << ax << endl;
    
    int a[105],tag[35];
    int main() {
        int ca;scanf("%d",&ca);
        while(ca--) {
            int n;scanf("%d",&n);
            memset(tag,0,sizeof(tag));
            for(int i = 1;i <= n;++i) {
                scanf("%d",&a[i]);
                for(int j = 0;j <= 30;++j) {
                    int g = ((a[i] >> j) & 1);
                    if(g == 0) tag[j] = 1;
                }
            }
            int ma = 0; 
            for(int i = 0;i <= 30;++i) {
                if(tag[i] != 1) ma += (1 << i);
            }
            printf("%d
    ",ma);
        }
    
    
     //   system("pause");
        return 0;
    }
    View Code

    B:每次都放置与前面不同显然最优,这里比较特殊的是以?开头,这时候要第一个字母和前面的问号不一样放置

    // Author: levil
    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    typedef pair<int,int> pii;
    const int N = 2e5 + 5;
    const int M = 5e5 + 5;
    const LL Mod = 1e9 + 7;
    #define pi acos(-1)
    #define INF 1e16
    #define dbg(ax) cout << "now this num is " << ax << endl;
    
    char s[105];
    char cal(char c) {
        if(c == 'B') return 'R';
        else return 'B';
    }
    int main() {
        int ca;scanf("%d",&ca);
        while(ca--) {
            int n;scanf("%d",&n);
            cin >> s;
            char pre = 'A';
            int len = 0;
            if(s[0] == '?') {
                for(int i = 0;i < n;++i) {
                    if(s[i] != '?') {pre = s[i];break;}
                    ++len;
                }
                if(pre == 'A') s[0] = 'B';
                else {
                    if(len % 2 == 0) s[0] = pre;
                    else s[0] = cal(pre);
                }
            }
            for(int i = 1;i < n;++i) {
                if(s[i] != '?') continue;
                s[i] = cal(s[i - 1]);
            }
            cout << s << endl;
        }
    
       // system("pause");
        return 0;
    }
    /*
    30
    7
    ??BBR??
    
    */
    View Code

    C:一开始直接冲哈密尔顿通路去了。仔细一看这个图其实比较特殊。

    然后分析一下就可以发现,如果存在到终点的路径,那么一定可以到。

    反之也一定到,因为如果存在到1的路径就可以从终点到1开始。

    综上所诉,一定存在一种走法满足。

    // Author: levil
    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    typedef pair<int,int> pii;
    const int N = 1e4 + 5;
    const int M = 5e5 + 5;
    const LL Mod = 1e9 + 7;
    #define pi acos(-1)
    #define INF 1e16
    #define dbg(ax) cout << "now this num is " << ax << endl;
    
    int a[N];
    vector<int> ans;
    void PR() {
        for(int i = 0;i < ans.size();++i) printf("%d%c",ans[i],i == ans.size() - 1 ? '
    ' : ' ');
    }
    int main() {
        int ca;scanf("%d",&ca);
        while(ca--) {
            int n;scanf("%d",&n);
            for(int i = 1;i <= n;++i) scanf("%d",&a[i]);
            ans.clear();
            if(n == 1) {
                if(a[1] == 0) ans.push_back(1),ans.push_back(2);
                else ans.push_back(2),ans.push_back(1);
                PR();
            }
            else {
                if(a[1] == 1) {
                    ans.push_back(n + 1);
                    for(int i = 1;i <= n;++i) ans.push_back(i);
                    PR();
                }
                else if(a[n] == 0) {
                    for(int i = 1;i <= n;++i) ans.push_back(i);
                    ans.push_back(n + 1);
                    PR();
                }
                else {
                    int st = 0;
                    for(int i = 1;i < n;++i) {
                        if(a[i] == 0 && a[i + 1] == 1) {
                            st = i;
                            break;
                        }
                    }
                    if(st != 0) {
                        for(int i = 1;i <= st;++i) ans.push_back(i);
                        ans.push_back(n + 1);
                        for(int i = st + 1;i <= n;++i) ans.push_back(i);
                        PR();
                    }   
                    //else printf("-1
    ");
                }
            }
        }
    
     //   system("pause");
        return 0;
    }
    View Code

    D1:直接n^2暴力并查集合并判断即可。

    // Author: levil
    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    typedef pair<int,int> pii;
    const int N = 1e3 + 5;
    const int M = 5e5 + 5;
    const LL Mod = 1e9 + 7;
    #define pi acos(-1)
    #define INF 1e16
    #define dbg(ax) cout << "now this num is " << ax << endl;
    
    int n,m1,m2,fa[N];
    namespace UN1{
        int fa[N];
        void init() {
            for(int i = 1;i <= n;++i) fa[i] = i;
        }
        int Find(int x) {
            return x == fa[x] ? x : fa[x] = Find(fa[x]);
        }
        void Merge(int x,int y) {
            x = Find(x),y = Find(y);
            fa[x] = y;
        }
        bool check(int x,int y) {
            x = Find(x),y = Find(y);
            return x != y;
        }
    }
    namespace UN2{
        int fa[N];
        void init() {
            for(int i = 1;i <= n;++i) fa[i] = i;
        }
        int Find(int x) {
            return x == fa[x] ? x : fa[x] = Find(fa[x]);
        }
        void Merge(int x,int y) {
            x = Find(x),y = Find(y);
            fa[x] = y;
        }
        bool check(int x,int y) {
            x = Find(x),y = Find(y);
            return x != y;
        }
    }
    int main() {
        scanf("%d %d %d",&n,&m1,&m2);
        UN1::init();
        UN2::init();
        while(m1--) {
            int u,v;scanf("%d %d",&u,&v);
            UN1::Merge(u,v);
        }
        while(m2--) {
            int u,v;scanf("%d %d",&u,&v);
            UN2::Merge(u,v);
        }
        vector<pii> vec;
        for(int i = 1;i <= n;++i) {
            for(int j = i + 1;j <= n;++j) {
                if(UN1::check(i,j) && UN2::check(i,j)) {
                    UN1::Merge(i,j);
                    UN2::Merge(i,j);
                    vec.push_back(pii{i,j});
                }
            }
        }
        printf("%d
    ",vec.size());
        for(auto v : vec) printf("%d %d
    ",v.first,v.second);
       // system("pause");
        return 0;
    }
    View Code

    D2:这里的思路还是比较抽象的感觉。

    枚举每个点和1的连接状态。如果对于当前点v,都和1没有连接。

    那么就可以加上Edeg{1,v}这条边。

    反之,准备两个容器v1,v2。对于没有和1连接的边,先放入容器。

    因为这些边可能由于和{i,i为和1同一并查集的某个点}连接而和1间接连接。

    现在我们考虑容器中的两个边x,y。

    他们肯定满足都不在1的连通块中,且他们在另一个森林中都和1在同一连通块中。(否则两个点就都在1的连通块中)

    即可以看成:

    {1 and y} ,{x}

    {1 and x} ,{y}

    那么就可以建立{x,y}这条边。

    所以对于容器中的任意两个点都可以建边。

    不过要注意的是,可能两个边连之后,容器中某些边都被合并在1的连通块中了。

    // Author: levil
    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    typedef pair<int,int> pii;
    const int N = 1e5 + 5;
    const int M = 5e5 + 5;
    const LL Mod = 1e9 + 7;
    #define pi acos(-1)
    #define INF 1e16
    #define dbg(ax) cout << "now this num is " << ax << endl;
    
    int n,m1,m2;
    namespace UN1{
        int fa[N];
        void init() {
            for(int i = 1;i <= n;++i) fa[i] = i;
        }
        int Find(int x) {
            return x == fa[x] ? x : fa[x] = Find(fa[x]);
        }
        void Merge(int x,int y) {
            x = Find(x),y = Find(y);
            fa[x] = y;
        }
        bool check(int x,int y) {
            x = Find(x),y = Find(y);
            return x != y;
        }
    }
    namespace UN2{
        int fa[N];
        void init() {
            for(int i = 1;i <= n;++i) fa[i] = i;
        }
        int Find(int x) {
            return x == fa[x] ? x : fa[x] = Find(fa[x]);
        }
        void Merge(int x,int y) {
            x = Find(x),y = Find(y);
            if(x < y) swap(x,y);
            fa[x] = y;
        }
        bool check(int x,int y) {
            x = Find(x),y = Find(y);
            return x != y;
        }
    }
    vector<pii> vec;
    vector<int> v1,v2;
    int main() {
        scanf("%d %d %d",&n,&m1,&m2);
        UN1::init();
        UN2::init();
        while(m1--) {
            int u,v;scanf("%d %d",&u,&v);
            UN1::Merge(u,v);
        }
        while(m2--) {
            int u,v;scanf("%d %d",&u,&v);
            UN2::Merge(u,v);
        }
    
        for(int i = 2;i <= n;++i) {
            if(UN1::check(1,i) && UN2::check(1,i)) {
                vec.push_back(pii{1,i});
                UN1::Merge(1,i);
                UN2::Merge(1,i);
            }
            else if(UN1::check(1,i)) v1.push_back(i);
            else if(UN2::check(1,i)) v2.push_back(i);
        }
        for(int i = 0,j = 0;i < v1.size() && j < v2.size();) {
            while(i < v1.size() && (!UN1::check(v1[i],1) && !UN2::check(v1[i],1))) {
                ++i;
            }
            while(j < v2.size() && (!UN2::check(v2[j],1) && !UN1::check(v2[j],1))) {
                ++j;
            }
            if(i >= v1.size() || j >= v2.size()) break;
            vec.push_back(pii{v1[i],v2[j]});
            UN1::Merge(v1[i],v2[j]);
            UN2::Merge(v2[j],v1[i]);
            ++i,++j;
        }
        printf("%d
    ",vec.size());
        for(auto v : vec) printf("%d %d
    ",v.first,v.second);
        //system("pause");
        return 0;
    }
    View Code

    E:这题挺不错的

    首先有个很直白的三维dp,但是显然不可能这样做。

    设dp[j] - 表示a1 + a2 + ... an == j的方案数。

    则有:

    $ans =sum_{a1 = L1}^{r1} sum_{a2 = L2}^{r2} ... sum_{an = Ln}^{rn} [gcd(a1,a2...an) = 1] * dp[a1,a2....an]$

    $ans = sum_{a1 = L1}^{r1} sum_{a2 = L2}^{r2} ... sum_{an = Ln}^{rn} sum_{d | (a1,a2...an)} mu (d)* dp[a1,a2....an]$

    $ans = sum_{d = 1}^{m} mu (d) sum_{a1 = [frac{L1}{d}]}^{[frac{r1}{d}]} sum_{a2 = [frac{L2}{d}]}^{[frac{r2}{d}]} ... sum_{an = [frac{Ln}{d}]}^{[frac{rn}{d}]} dp[a1 * d,a2 * d....an * d]$

    到这一步我们可以发现,我们只需要满足a1d + a2d + a3d + ... + and <= m

    即$a1 + a2 + a3 + .. an <= [frac{m}{d}]$

    至此,对于每个d,贡献即为$sum_{i = 1}^{[frac{m}{d}]}dp[i] * mu (d)$

    考虑一下复杂度优化:对于dp[j]的计算,枚举d,n,对于第三维,我们只需要到m / d,

    平摊下来复杂度接近O(N * M)。

    一些细节:对于dp[j]的计算,我们可以利用前缀和来优化掉一维。

    然后考虑一下我们的上界和下界。

    如果我们当前ai ~ [1.5,3.5],那么我们的上界应该是2,3,因为我们1和4应该是取不到的。

    所以我们对于下界应该向上取整。

    // Author: levil
    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    typedef pair<int,int> pii;
    const int N = 1e5 + 5;
    const int M = 5e5 + 5;
    const LL Mod = 998244353;
    #define pi acos(-1)
    #define INF 1e16
    #define dbg(ax) cout << "now this num is " << ax << endl;
    
    int n,m,L[55],r[55],prime[N],tot = 0;
    LL dp[55][N],sum[55][N],mu[N];
    bool vis[N];
    void init() {
        mu[1] = 1;
        for(int i = 2;i < N;++i) {
            if(!vis[i]) {
                prime[++tot] = i;   
                mu[i] = -1;
            }
            for(int j = 1;j <= tot && prime[j] * i < N;++j) {
                vis[i * prime[j]] = 1;
                if(i % prime[j] == 0) break;
                else mu[i * prime[j]] = -mu[i];
            }
        }
    }
    int main() {
        init();
        scanf("%d %d",&n,&m);
        for(int i = 1;i <= n;++i) scanf("%d %d",&L[i],&r[i]);
        LL ans = 0;
        for(int d = 1;d <= m;++d) {
            dp[0][0] = 1;
            for(int i = 1;i <= n;++i) {
                sum[i - 1][0] = dp[i - 1][0];
                for(int j = 1;j <= m / d;++j) {
                    sum[i - 1][j] = (sum[i - 1][j - 1] + dp[i - 1][j]) % Mod;
                }
                int le = (L[i] + d - 1) / d,ri = r[i] / d;//le向上取整,ri向下取整
                for(int j = le;j <= m / d;++j) {
                    if(j - ri - 1 < 0) dp[i][j] = sum[i - 1][j - le];
                    else dp[i][j] = sum[i - 1][j - le] - sum[i - 1][j - ri - 1];
                    //dp[i][j] = sum[i - 1][j - le] - sum[i - 1][max(0,j - ri)];0也应该算在贡献里
                    dp[i][j] = (dp[i][j] + Mod) % Mod;
                }
            }
            LL cnt = 0;
            for(int j = 1;j <= m / d;++j) cnt = (cnt + dp[n][j]) % Mod;
            ans = (ans + cnt * (mu[d]) % Mod) % Mod;
            ans = (ans + Mod) % Mod;
        }
        printf("%lld
    ",ans);
    
        system("pause");
        return 0;
    }
    View Code
  • 相关阅读:
    SkyWalking链路追踪系统-告警篇
    在k8s中解决pod资源的正确识别
    SkyWalking链路追踪系统-接入篇
    Jenkins API+Pipeline深度实践之input的自动化
    SkyWalking链路追踪系统-部署篇
    DevOps建设之基于钉钉OA审批流的自动化上线
    使用kube-prometheus部署k8s监控(最新版)
    基于k8s手动部署rabbitmq集群
    ant desgin vue中table复选框根据状态disabled置灰
    ant design vue 中tree实现单选
  • 原文地址:https://www.cnblogs.com/zwjzwj/p/15160065.html
Copyright © 2020-2023  润新知