Educational Codeforces Round 71 (Rated for Div. 2)简要题解

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/qq_42671946/article/details/100706216

A - There Are Two Types Of Burgers

分析:分一下两种汉堡的加个大小讨论一下就可以了。

#include "bits/stdc++.h"
 
using namespace std;
 
struct edge {
    int u, v, w;
 
    bool friend operator<(edge a, edge b) {
        return a.w < b.w;
    }
} e[200004];
 
int fa[200004];
int num[200004];
 
int Find(int a) {
    if (a == fa[a])return a;
    else return fa[a] = Find(fa[a]);
}
 
pair<int, int> que[200004];
long long ans[200004];
 
int main() {
    int t;
    cin>>t;
    while(t--){
        int b,p,f,h,c;
        cin>>b>>p>>f>>h>>c;
        if(h>c){
            int ans = 0;
            int num = min(b/2,p);
            ans += num * h;
            b-=num*2;
            num = min(b/2,f);
            ans += num * c;
            cout<<ans<<endl;
        }
        else {
            int ans = 0;
            int num = min(b/2,f);
            ans += num * c;
            b-=num*2;
            num = min(b/2,p);
            ans += num * h;
            cout<<ans<<endl;
        }
    }
}

B - Square Filling

分析:首先认为操作时对于2*2矩阵左上角的点。那么遍历到点(i,j)时,若这个点在a中时1,在b中还是0,那么这个点一定会进行操作,那么只需要判断一下这个点进行操作后会不会出现不合法的情况就可以了。

#include "bits/stdc++.h"
 
using namespace std;
int a[100][100];
int b[100][100];
int main() {
    int n, m;
    cin >> n >> m;
    for (int i = 1; i <= n; ++i) {
        for (int j = 1; j <= m; ++j) {
            cin>>a[i][j];
        }
    }
    memset(b,0, sizeof(b));
    vector<pair<int,int>>v;
    for (int i = 1; i < n; ++i) {
        for (int j = 1; j < m; ++j) {
            if(a[i][j]==1 ){
                bool ok = 1;
                for (int x = 0; x < 2; ++x) {
                    for (int y = 0; y < 2; ++y) {
                        if(a[i+x][j+y]==0){
                            ok = 0;
                        }
                    }
                }
                if(ok){
                    v.push_back(make_pair(i,j));
                    for (int x = 0; x < 2; ++x) {
                        for (int y = 0; y < 2; ++y) {
                            b[i+x][j+y]=1;
                        }
                    }
                }
            }
        }
    }
    bool ok = 1;
    for (int i = 1; i <= n; ++i) {
        for (int j = 1; j <= m; ++j) {
            if(a[i][j]!=b[i][j])ok= 0;
        }
    }
    if(ok){
        printf("%d\n",v.size());
        for (int i = 0; i < v.size(); ++i) {
            printf("%d %d\n",v[i].first,v[i].second);
        }
    }
    else puts("-1");
}

C - Gas Pipeline

分析:对于一段连续的0,比较一下放下去和抬起来的成本就可以了。

#include "bits/stdc++.h"
 
using namespace std;
char s[200004];
 
int main() {
    int t;
    cin >> t;
    while (t--) {
        long long n, a, b;
        cin >> n >> a >> b;
        scanf("%s", s);
        long long ans = n * a + (n - 1) * 2 * b + 2LL * (a + b);
        bool ok = 0;
        for (int i = 0; i < n; ++i) {
            if (s[i] == '1')ok = 1;
        }
        if (!ok) {
            printf("%lld\n", n * a + (n + 1) * b);
        } else {
            int l, r;
            for (int i = 1; i < n; ++i) {
                if (s[i] == '0') {
                    ans -= b;
                } else {
                    l = i;
                    break;
                }
            }
            for (int i = n - 2; i >= 0; --i) {
                if (s[i] == '0') {
                    ans -= b;
                } else {
                    r = i;
                    break;
                }
            }
            for (int i = l; i <= r; ++i) {
                long long len = 0;
                while (s[i] == '0') {
                    len++;
                    i++;
                }
                if ((len - 1) * b > 2LL * a) {
                    ans += 2LL * a - (len - 1) * b;
                }
            }
            cout << ans << endl;
        }
    }
}

 

D - Number Of Permutations

分析:good string 定义为对于a,b都不是非下降序列,那么bad string 就是对于ab存在一个是非下降序列。

bad string 的个数为sum,答案就为N!-sum。

定义a有序,b随意的个数为x;

定义b有序,a随意的个数为y;

定义ab都有序的个数为z;

那么显而易见,sum = x + y - z

那么乱搞一下就可以了。

#include "bits/stdc++.h"
 
using namespace std;
const int mod = 998244353;
long long fac[300004];
pair<int, int> p[300004];
int num1[300004], num2[300004];
void init(int n) {
    memset(num1, 0, sizeof(num1));
    memset(num2, 0, sizeof(num2));
    fac[0] = 1;
    for (int i = 1; i <= n; ++i) {
        fac[i] = fac[i - 1] * i % mod;
    }
}
 
 
int main() {
    int n;
    cin >> n;
    init(n);
    int x, y;
    for (int i = 0; i < n; ++i) {
        scanf("%d%d", &x, &y);
        p[i] = make_pair(x, y);
        num1[x]++;
        num2[y]++;
    }
    long long ans = 0, p1 = 1, p2 = 1,p3 = 1;
    for (int i = 1; i <= n; ++i) {
        p1 = p1 * fac[num1[i]] % mod;
        p2 = p2 * fac[num2[i]] % mod;
    }
    ans = (p1 + p2) % mod;
    sort(p,p+n);
    bool ok = 1;
    for (int i = 1; i < n; ++i) {
        if(p[i-1].second > p[i].second)ok = 0;
    }
    if(ok){
        for (int i = 0; i < n; ++i) {
            int len = 1;
            while(i+1<n && p[i]==p[i+1]){
                i++;
                len++;
            }
            p3 = p3 * fac[len] % mod;
        }
        ans = (ans - p3 + mod)%mod;
    }
    cout<<(fac[n]-ans+mod)%mod<<endl;
}

 

E - XOR Guessing

分析:题目告诉你有

a_i XORans=x

b_jXORans=y

那么可以得到xXORy=a_iXORb_j

只要对于任意两个ai,bj的异或和不重复就可以了。那么直接构造一个这样的序列,就可以了。

#include "bits/stdc++.h"
using namespace std;
int a[104],b[104];
unordered_map<int,int>mp;
bool check(int n){
    for (int i = 1; i < 100; ++i) {
        int temp = i^n;
        if(mp.count(temp))return 0;
    }
    return 1;
}
int main(){
    for (int i = 1; i <= 100; ++i) {
        a[i] = i;
    }
    int now = 101;
    for (int i = 1; i <= 100; ++i) {
        while (!check(now)){now++;}
        b[i]=now;
        for (int j = 1; j <= 100; ++j) {
            mp[now^j]=1;
        }
    }
    int x,y;
    printf("?");
    for (int i = 1; i <= 100; ++i) {
        printf(" %d",i);
    }
    puts("");
    fflush(stdout);
    scanf("%d",&x);
    printf("?");
    for (int i = 1; i <= 100; ++i) {
        printf(" %d ",b[i]);
    }
    puts("");
    fflush(stdout);
    scanf("%d",&y);
 
    x^=y;
    printf("! ");
    for (int i = 1; i <= 100; ++i) {
        for (int j = 1; j <= 100; ++j) {
            if((i^b[j])==x)
                return 0*printf("%d\n",y^b[j]);
        }
    }
}

 

F - Remainder Problem

分析:首先我们想一想暴力该怎么写。

(1)每次查询,暴力找y,y+x,y+2x……求和。当x较大时可行

(2)每次操作1时,把这个数对所有模数取模都存下来,查询时直接输出。当x较小时可行。

那么这题就做完了,当x<sqrt(500000)时,存下来输出,否则暴力。

#include "bits/stdc++.h"
 
using namespace std;
int a[500004];
int init[704][704];
int main() {
    int q;
    cin >> q;
    while (q--) {
        int op, x, y;
        scanf("%d%d%d",&op,&x,&y);
        if(op == 1){
            a[x]+=y;
            for (int i = 1; i <= 700; ++i) {
                init[i][x%i]+=y;
            }
        }
        else {
            if(x <= 700){
                printf("%d\n",init[x][y]);
            }
            else {
                int ans = 0;
                while(y <= 500000){
                    ans += a[y];
                    y += x;
                }
                printf("%d\n",ans);
            }
        }
    }
}

 

猜你喜欢

转载自blog.csdn.net/qq_42671946/article/details/100706216