AtCoder Beginner Contest 159

Posted zdragon1104

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了AtCoder Beginner Contest 159相关的知识,希望对你有一定的参考价值。

传送门

A - The Number of Even Pairs

技术图片
#include <bits/stdc++.h>
#define ll long long
using namespace std;
int main() {
    //freopen("in.txt","r",stdin);
    int n,m;
    scanf("%d%d",&n,&m);
    printf("%d
",n*(n-1)/2+m*(m-1)/2);
    return 0;
}
A.cpp

B - String Palindrome

技术图片
#include <bits/stdc++.h>
#define ll long long
using namespace std;
char s[105];
bool cal(int l,int r) {
    for(int i=l;i<=r;i++) {
        if(s[i]!=s[r+l-i]) return false;
    }
    return true;
}
int main() {
    //freopen("in.txt","r",stdin);
    scanf("%s",s+1);
    int n=strlen(s+1);
    bool f=true;
    if(!cal(1,n)) f=false;
    if(!cal(1,(n-1)/2)) f=false;
    if(!cal((n+3)/2,n)) f=false;
    printf("%s
",f?"Yes":"No");
    return 0;
}
B.cpp

C - Maximum Volume

题意:已知长方体的长+宽+高等于L,求长方体的最大体积。

数据范围:$1 leq L leq 1000$

题解:长方体最大体积时,长=宽=高=L/3。

技术图片
#include <bits/stdc++.h>
#define ll long long
using namespace std;
int main() {
    //freopen("in.txt","r",stdin);
    double L;
    scanf("%lf",&L),L/=3;
    printf("%.12f
",L*L*L);
    return 0;
}
C.cpp

D - Banned K

题意:给N个球,每个球上有数字Ai,求去掉第i个球以后,选两个相同数字的球的方案数。

数据范围:$3 leq N leq 2 imes 10^{5},1 leq A_{i} leq N$

题解:先算出不去掉任何球的方案数,即为每个数字个数中取两个的组合数总和。

去掉第i个球,先减去该球上sum[Ai]对答案的贡献,然后加上C(sum[Ai]-1,2)。

技术图片
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int N=2e5+5;
int a[N],num[N];
int main() {
    //freopen("in.txt","r",stdin);
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;i++) {
        scanf("%d",&a[i]);
        num[a[i]]++;
    }
    ll ans=0;
    for(int i=1;i<=n;i++) {
        ans+=1LL*num[i]*(num[i]-1)/2;
    }
    for(int i=1;i<=n;i++) {
        ans-=1LL*num[a[i]]*(num[a[i]]-1)/2;
        num[a[i]]--;
        printf("%lld
",ans+1LL*num[a[i]]*(num[a[i]]-1)/2);
        num[a[i]]++;
        ans+=1LL*num[a[i]]*(num[a[i]]-1)/2;
    }
    return 0;
}
D.cpp

E - Dividing Chocolate

题意:给一个H*W的矩阵,其中’0‘代表该点为黑,’1‘代表该点为白,可以进行横着或竖着切,求至少切几次满足每块的白块不超过K块。

数据范围:$1 leq H leq 10,1leq W leq 1000,1 leq K leq H imes W$

题解:由于H很小,可以枚举横着切的情况,然后就是枚举每列求最小次数。

技术图片
#include <bits/stdc++.h>
using namespace std;
const int N=1e3+5;
char s[15][N];
int a[15][N];
int cal(int x1,int x2,int y) {
    int ans=0;
    for(int i=x1;i<=x2;i++) {
        ans+=(s[i][y]==1);
    }
    return ans;
}
int main() {
    //freopen("in.txt","r",stdin);
    int n,m,k;
    scanf("%d%d%d",&n,&m,&k);
    for(int i=0;i<n;i++) {
        scanf("%s",s[i]);
    }
    int ans=1e9;
    for(int s=0;s<(1<<(n-1));s++) {
        vector<int> vec;
        vec.push_back(-1);
        for(int i=0;i<n-1;i++) {
            if((1<<i)&s) vec.push_back(i);
        }
        vec.push_back(n-1);
        int sz=vec.size();
        bool f=true;
        for(int j=0;j<m;j++) {
            for(int i=1;i<sz;i++) {
                a[i][j]=cal(vec[i-1]+1,vec[i],j);
                if(a[i][j]>k) f=false;
            }   
        }
        if(!f) continue;
        int num=0,b[15]={0};
        for(int j=0;j<m;j++) {
            bool f=true;
            for(int i=1;i<sz;i++) {
                b[i]+=a[i][j];
                if(b[i]>k) f=false;
            }
            if(!f) {
                num++;
                for(int i=1;i<sz;i++) {
                    b[i]=a[i][j];
                }
            }
        }
        ans=min(ans,sz-2+num);
    }
    printf("%d
",ans);
    return 0;
}
E.cpp

F - Knapsack for All Segments

题意:给一个长度为N的序列A,定义f(L,R)为AL~AR中子序列总和为S的方案数,求$sum_{L=1}^{N} sum_{R=L}^{N} f(L,R) $(对998244353取模)。

数据范围:$1 leq N,S,A_{i} leq 3000$

题解:通过朴素的01背包可以求出1~[1,N]的所有数,然后需要求2~[2,N]、3~[3,N]的总和,可以在第i个位置加一个起点,也就是f[0]++,这样就能合并在一起。

技术图片
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int N=3e3+5;
const int MD=998244353;
int a[N],f[N];
void add(int &x,int y) {
    x+=y;
    if(x>=MD) x-=MD;
}
int main() {
    //freopen("in.txt","r",stdin);
    int n,s;
    scanf("%d%d",&n,&s);
    for(int i=0;i<n;i++) {
        scanf("%d",&a[i]);
    }
    int ans=0;
    for(int i=0;i<n;i++) {
        add(f[0],1);
        for(int j=s;j>=a[i];j--) {
            add(f[j],f[j-a[i]]);
        }
        add(ans,f[s]);
    }
    printf("%d
",ans);
    return 0;
}
F.cpp

 

以上是关于AtCoder Beginner Contest 159的主要内容,如果未能解决你的问题,请参考以下文章

AtCoder Beginner Contest 234

AtCoder Beginner Contest 115 题解

AtCoder Beginner Contest 154 题解

AtCoder Beginner Contest 103

AtCoder Beginner Contest 228

AtCoder Beginner Contest 242