ABC363

A

题意: 给一个当前分数,问距离下一个分数段还差多少分

题解:

#include<bits/stdc++.h>
using namespace std;
int main()
{
    int n;
    cin >> n;
    if(n < 100)
        cout << 100 - n << endl;
    else if(n < 200)
        cout << 200 - n << endl;
    else if(n < 300)
        cout << 300 - n << endl;
    else
        cout << 400 - n << endl;
        
    return 0;
}

B

题意: 把题意换种说法,有 n n n棵树,每天生长一米,初始高度为 a i a_i ai,问到第几天的时候,有 p p p棵树可以长到 t t t米。

题解: 把不足 t t t米的树存起来,但是存的时候存与 n n n米的差,也就是存 n − a i n - a_i nai,如果当前树已经大于 t t t米了,那么 p p p减一,如果 p p p大于0,那么将存起来的值小根堆排序,输出第 p p p个元素,否则输出 0 0 0

#include<bits/stdc++.h>
using namespace std;
int main()
{
    int n, t, p;
    cin >> n >> t >> p;
    vector<int> a;
    for(int i = 1; i <= n; i ++)
    {
        int x;
        cin >> x;
        if(x >= t)
            p --;
        else
            a.push_back(t - x);
    }
    if(p <= 0)
        cout << 0 << endl;
    else
    {
        sort(a.begin(), a.end());
        cout << a[p - 1] << endl;
    }
    return 0;
}

C

题意: 给你一个长度为 n n n的字符串 s s s,问 s s s的所有排列中,不包含长度为 k k k的子串是回文串的数量。

题解: 用全排列函数枚举出 s s s的所有情况,然后暴力判断长度为 k k k的字符串就行了。

#include<bits/stdc++.h>
using namespace std;
int main()
{
    int n, k;
    cin >> n >> k;
    string s;
    cin >> s;
    sort(s.begin(), s.end());	//先将s排个序
    int ans = 0;
    do
    { 
        auto check = [&](string t)	//lambda表达式,就是作为一个函数。
        {
            for(int i = 0, j = k - 1; i < j; i ++, j --)
                if(t[i] != t[j])
                    return true;
            return false;
        };
        bool is_find = true;
        for(int i = 0; i + k <= s.size(); i ++)
        {
            string t = s.substr(i, k);
            if(check(t))
                continue;
            is_find = false;
        }
        if(is_find)
            ans ++;
    }while(next_permutation(s.begin(), s.end()));	//全排列函数
    cout << ans << endl;
    return 0;
}

D

题意: 一个非负的十进制整数 x x x如果是回文,则被称为回文数,例如( 363 , 12344321 , 0 363, 12344321, 0 363,12344321,0)都是回文数,问第 n n n个回文数是多少。

题解: 打表先找一下规律,发现 1 1 1位的有 10 10 10个, 2 2 2位有 9 9 9个, 3 3 3位的有 90 90 90个, 4 4 4位的有 90 90 90 . . . ... ...以此类推,那么可以 c n t i cnt_i cnti表示,长度为 i i i的十进制数中,回文数有 c n t i cnt_i cnti个。然后将这个数字从头到尾一位位的拆分并且按照顺寻放下就可以了。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int main()
{
    ll n;
    cin >> n;
    vector<ll> cnt(40);  //发现长度最大为38就够了
    ll t = 90;
    cnt[1] = 10, cnt[2] = 9;
    int tot = 0;
    for(int i = 3; i < 39; i ++)
    {
        cnt[i] = t;
        tot ++;
        if(tot == 2)
        {
            tot = 0;
            t *= 10;
        }
    }
    if(n <= 10)
    {
        cout << n - 1 << endl;
        return ;
    }

    n --;
    vector<int> ans(50);
    for(int i = 1; i < 39; i ++)
    {
        if(n > cnt[i])
            n -= cnt[i];
        else
        {
            ll x = cnt[i] / 9;
            if(n > 0)
                ans[0] = ans[i - 1] = 1 + n / x;
            n %= x;
            for(int j = 1; j <= i / 2; j ++)
            {
                x /= 10;
                if(n == 0 or x == 0)
                    break;
                ans[j] = ans[i - j - 1] = n / x;
                n %= x;
            }
            for(int j = 0; j < i; j ++)
                cout << ans[j];
            cout << endl;
            break;
        }
    }
    return 0;
}

题意: 有一个 n ∗ m n * m nm大小的岛屿,岛屿每一个位置的高度是 g i j g_{ij} gij,海水从四周淹没岛屿,水位每天增加一米的高度,问 1 1 1 h h h天,岛屿每天剩余的面积是多少。

题解: b f s bfs bfs+前缀和。根据高度分出不同的情况,开 h h h个队列,把不同高度的岛屿区分开,先将四周高度小于 h h h的放进去,然后从小到大去枚举高度,加入一个新的点的时候,考虑当前高度和下一个点的高度取最大值,即 m a x ( k , g [ a ] [ b ] ) max(k, g[a][b]) max(k,g[a][b])

#include<bits/stdc++.h>
using namespace std;
#define fir first
#define sec second
typedef pair<int,int> pii;

int main()
{
    int n, m, h;
    cin >> n >> m >> h;
    vector<vector<int>> g(n + 1, vector<int>(m + 1));
    //每个点的高度
    vector<vector<int>> vis(n + 1, vector<int>(m + 1));
    //每个点是否被遍历过
    vector<int> ans(h + 1);
    //前缀和数组(代表有多少个点被淹没了)
    queue<pii> q[h + 1];
    //h个队列,分别对应[1, h]高度的位置。
    for(int i = 1; i <= n; i ++)
        for(int j = 1; j <= m; j ++)
        {
            cin >> g[i][j];
            if(g[i][j] > h)	//如果当前的点大于h,那么一定不会被淹没,不用加入队列
                continue;
            if(i == 1 or j == 1 or i == n or j == m)
            //如果当前是四周,那么就加入对应高度的队列中
            {
                vis[i][j] = 1;
                q[g[i][j]].push({i, j});
                ans[g[i][j]] ++;	
                //高度为g[i][j]的点数量+1,比这个高度高的点数量都要+1
            }
        }
    array<int, 4> dx {0, 0, -1, 1};
    array<int, 4> dy {-1, 1, 0, 0};
    //四周遍历的方向
    for(int k = 1; k <= h; k ++)
    {
        while(q[k].size())
        {
            auto t = q[k].front();
            q[k].pop();

            int x = t.fir, y = t.sec;
            for(int i = 0; i < 4; i ++)
            {
                int a = x + dx[i], b = y + dy[i];
                if(a > n or b > m or a < 1 or b < 1)
                    continue;
                if(vis[a][b])
                    continue;
                if(g[a][b] > h)
                    continue;
                vis[a][b] = 1;
                ans[max(k, g[a][b])] ++;
                //考虑当前点如果是2,g[a][b]是1,如果放到g[a][b],那么会导致浪费一个点。
			   //如果当前是1, g[a][b]是2,在1的位置+1,那么会导致后边大小出问题
                q[max(k, g[a][b])].push({a, b});
            }
        }
    }
    
    for(int i = 1; i <= h; i ++)
        ans[i] += ans[i - 1];	//前缀和
    for(int i = 1; i <= h; i ++)
        cout << n * m - ans[i] << endl;	//整个图-被淹没的
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值