AtCoder Beginner Contest 363 A~E

A.Piling Up(思维)

题意:

A t C o d e r AtCoder AtCoder中,用户的评分以正整数形式给出,并根据该值显示一定数量的^。具体来说,当评分介于 1 1 1 399 399 399之间(含)时,显示规则如下:

  • 当评级介于 1 1 1 99 99 99(含)之间时,显示一次^
  • 当评级介于 100 100 100 199 199 199(含)之间时,^会显示两次。
  • 当评级介于 200 200 200 299 299 299(含)之间时,^会显示三次。
  • 当评级介于 300 300 300 399 399 399(含)之间时,^会显示四次。

目前,高桥的评分是 R R R。这里可以保证 R R R是介于 1 1 1 299 299 299之间的整数。
求他增加显示的^所需的最小评分增幅。
可以证明,在这个问题的限制条件下,他可以增加^的数量,而不需要将他的评分提高到 400 400 400或更高。

分析:

求某个数距离比它大的最近的一个 k × 100 k\times 100 k×100的距离是多少。

代码:

#include<bits/stdc++.h>
typedef long long LL;
using namespace std;
const int N=250005;
const int MOD=1000000007;

int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    int R;
    cin>>R;
    int cnt=R/100;
    cout<<(cnt+1)*100-R<<endl;
    return 0;
}

B.Japanese Cursed Doll(排序)

题意:

N N N个人,第 i i i ( 1 ≤ i ≤ N ) (1\leq i\leq N) (1iN)人当前的头发长度是 L i L_i Li
每个人的头发每天增长 1 1 1

请输出头发长度至少为 T T T的人数首次变为 P P P或更多的天数。
如果现在头发长度至少为 T T T的人数已经为 P P P或更多,则输出 0 0 0

分析:

L L L从小往大排序,那么只需要第 n − P + 1 n−P+1 nP+1大的数满足条件即可,假设这个数是 a a a。因此,只需要计算 T − a T−a Ta即可。

如果这个数是负数,意味着初始时就满足条件,此时要输出 0 0 0

代码:

#include<bits/stdc++.h>
typedef long long LL;
using namespace std;
const int N=105;
const int MOD=1000000007;
int n,T,P;
int L[N];

int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    cin>>n>>T>>P;
    for(int i=1;i<=n;++i)
        cin>>L[i];
    sort(&L[1],&L[n+1]);
    int l=L[n-P+1];
    int ans=max(0,T-l);
    cout<<ans<<endl;
    return 0;
}

C.Avoid K Palindrome 2(字符串)

题意:

给你一个长度为 N N N的字符串 S S S,它只由小写英文字母组成。

求将 S S S的字符(包括字符串 S S S本身)置换后得到的字符串中,不包含长度为 K K K的回文字符串作为子串的字符串的个数。

这里,当且仅当存在一个不大于 ( N − K ) (N-K) (NK)的非负整数 i i i,使得每个整数 j j j 1 ≤ j ≤ K 1\leq j\leq K 1jK都有 T i + j = T i + K + 1 − j T_{i+j}=T_{i+K+1-j} Ti+j=Ti+K+1j时,长度为 N N N的字符串 T T T才被称为 “包含长度为 K K K的回文字符串作为子串”。

这里, T k T_k Tk表示字符串 T T T的第 k k k个字符。

分析:

观察数据范围,直接枚举字符串 s s s的所有排列,然后暴力找有没有长度为 k k k的回文字符串即可。需要去重。

枚举字符串所有排列可以先给字符串排序,然后用next_permutation找下一个排列。

代码:

#include<bits/stdc++.h>
typedef long long LL;
using namespace std;
const int N=105;
const int MOD=1000000007;

int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    LL n,k;
    cin>>n>>k;
    set<string>se;
    string s;
    cin>>s;
    sort(s.begin(), s.end());
    do{
        LL ok=1;
        for(int i=0,j=k-1;j<n;++i,++j) {
            string tmp;
            for(int p=i;p<=j;++p)
                tmp+=s[p];
            string we=tmp;
            reverse(we.begin(),we.end());
            if(we==tmp){
                ok=0;
                break;
            }
        }
        if(ok) 
            se.insert(s);
    }while(next_permutation(s.begin(),s.end()));
    cout<<se.size()<<endl;
    return 0;
}

D.Palindromic Number(数学)

题意:

如果一个非负整数 X X X的十进制表示(不含前导零)是一个回文数,那么这个非负整数 X X X就叫做回文数。
例如, 363 363 363 12344321 12344321 12344321 0 0 0都是回文数。

求第 N N N小的回文数。

分析:

因为是回文数,所以只需要考虑前一半就可以进行构造。

枚举长度,首先计算出答案回文数的长度。通过枚举和减法可以计算出是当前长度下第 k k k大的回文数。而前一半就是顺序的,第 k k k大就是当前长度的数的第 k k k大,这个很好求。接下来只需要构成回文,直接输出即可。

代码:

#include<bits/stdc++.h>
typedef long long LL;
using namespace std;
LL N;
int a[1000];
LL fpow(LL a,LL b){
    LL ret=1;
    while(b){
        if(b&1)
            ret*=a;
        a*=a;
        b>>=1;
    }
    return ret;
}

int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    cin>>N;
    N-=1;
    if(N<10){
        cout<<N<<endl;
        return 0;
    }
    int l=1;
    while(true){
        int t=(l+1)>>1;
        LL m=9ll*fpow(10,t-1);
        if(N>m)
            N-=m;
        else 
            break;
        ++l;
    }
    int t=(l+1)>>1;
    int len=0;
    N-=1;
    while(N){
        a[++len]=N%10;
        N/=10;
    }
    a[t]+=1;
    for(int i=t;i;--i)
        cout<<a[i];
    for(int i=1+(l&1);i<=t;++i)
        cout<<a[i];
    cout<<endl;
    return 0;
}

E.Sinking Land(搜索)

题意:

有一个面积为 H × W H\times W H×W的小岛,四面环海。
该岛被分成 H H H行和 W W W列的 1 × 1 1\times 1 1×1部分,从顶部起 i i i行和从左侧起 j j j列的部分(相对于当前海平面)的海拔高度为 A i , j A_{i,j} Ai,j

从现在开始,海平面每年上升 1 1 1
在这里,垂直或水平临海的地段或沉入海中的地段,其标高不大于海平面,就会沉入海中。
在此,当一个断面新沉入海中时,任何垂直或水平相邻且标高不高于海平面的断面也将同时沉入海中,新沉入海中的断面重复这一过程。

对于每个 i = 1 , 2 , … , Y i=1,2,\ldots,Y i=1,2,,Y,求 i i i年后该岛仍高于海平面的面积。

分析:

首先简单粗暴的考虑一下,对于每个海平面高度进行 b f s bfs bfs,在队列中找到不大于海平面的区域就拓展,并统计,计算一下发现此方法会TLE。

观察题目和数据,可以发现海平面为 a a a时沉没的区域,在海平面为 ( a + 1 ) (a+1) (a+1)时一定也会沉没。所以,不需要每次都重新 b f s bfs bfs,直接按着上一次的结果继续即可。同时我们还可以继续优化,找到不大于海平面的区域这一步,可以使用堆进行优化,一直取出当前堆内海拔最低的区域看是否被淹没,如果是就拓展,否则结束。

代码:

#include<bits/stdc++.h>
typedef long long LL;
using namespace std;
const int N=1005;
const int nx[4] = {1,0,-1,0};
const int ny[4] = {0,1,0,-1};
int h,w,y,a[N][N],t,ans;
struct Node{
  int x,y,h;
  bool operator < (const Node & a) const{
    return a.h<h;
  }
};
bool book[N][N];

int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    cin>>h>>w>>y;
    ans=h*w;
    for(int i=1;i<=h;i++)
        for(int j=1;j<=w;j++)
            cin>>a[i][j];
    priority_queue<Node> q;
    for(int i=1;i<=h;i++)
        for(int j=1;j<=w;j++)
            if(i==1||j==1||i == h||j == w){
                book[i][j]=1;
                q.push({i,j,a[i][j]});
            }
    while(y--){
        ++t;
        while(1 && !q.empty()){
            Node now=q.top();
            if(now.h<=t){
                --ans;
                q.pop();
                for(int i=0;i<4;i++){
                    int tx=now.x+nx[i];
                    int ty=now.y+ny[i];
                    if(tx>=1 && tx<=h && ty>=1 && ty<=w && !book[tx][ty]){
                        q.push({tx,ty,a[tx][ty]});
                        book[tx][ty]=1;
                    }
                }
            }
            else 
                break;
        }
        cout<<ans<<endl;
    }
    return 0;
}

赛后交流

在比赛结束后,会在交流群中给出比赛题解,同学们可以在赛后查看题解进行补题。

群号: 704572101,赛后大家可以一起交流做题思路,分享做题技巧,欢迎大家的加入。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值