牛客网OJ题解--20210328

C 涂墙

https://ac.nowcoder.com/acm/contest/13882/C

本系列记录翀翀😐痛苦的刷题日志,所有题目均来自于牛客网OJ题目,坚持刷题谈起来容易做起来难,希望我可以坚持下去,这里仍然分享一段励志文案:每个人都有梦想,然而有些人把梦想变成了现实,有些人的梦想依旧是梦想,只因为他们为梦想付出的努力程度不一样,他们坚持的时间不一样,最终才有这样的结果。

NC13882_C-涂墙

题目链接

https://ac.nowcoder.com/acm/contest/13882/C

题目描述

母牛哥有一桶油漆,把它用完可以给n平方米的墙涂上颜色. 母牛哥想要在墙上涂5个正方形(这些正方形的边长都是整数,单位是米),并且刚好把油漆用完. 母牛哥能做到吗?

第一行一个数字t(<=1000),表示测试样例数量

接下来t行,每行一个数字n(0<=n<=1000000),表示母牛哥的油漆可以涂多少平方米.

输出t行,对于每个输入.如果母牛哥能够做到,就输出YES.否则输出NO.

测试样例

输入

2
4
55

输出

NO
YES

说明

4显然不能分解成5个正平方数,所以这桶油漆不能涂5个正方形.
55可以涂5个正方形,他们面积分别是1 4 9 16 25.

解题思路

一开始想的就是dfs,逐一尝试但是超时。。后来借鉴大佬的代码,使用打表枚举发现规律,只有几个数不满足,其他数都是满足条件的。

解题代码

dfs(虽然没过,但好歹练习了一下)

#include <bits/stdc++.h>
using namespace std;
const long long N = 1e5;
long long n;
bool ok = false;

//这次要加的数,和,加的次数
void dfs(long long x, long long sum, long long num)
{
    if (x >= n)
        return;
    if (num == 5)
    {
        if (sum == n)
        {
            ok = true;
        }
        return;
    }
    //不选这个数x
    dfs(x + 1, sum, num);
    sum += x * x;
    if (sum > n)
    {
        return;
    }
    //选了这个数x,并且下一个还是选x
    dfs(x, sum, num + 1);
    //选了这个数x,并且下一个数选x+1
    dfs(x + 1, sum, num + 1);
}
int main()
{
    long long t;
    cin >> t;
    while (t--)
    {
        ok = false;
        cin >> n;
        //从1开始
        dfs(1, 0, 0);
        if (ok)
            cout << "YES" << endl;
        else
            cout << "NO" << endl;
    }
    system("pause");
    return 0;
}

打表发现规律以后特判

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

signed main() {
    ios::sync_with_stdio(false), cin.tie(0);
    ll t;
    cin >> t;
    while (t--) {
        ll n;
        cin >> n;
        if (n == 5 || n == 8 || n == 11 || n == 13 || n == 14 || n == 16 || n == 17 || (n != 33 && n >= 19))
            cout << "YES" << endl;
        else
            cout << "NO" << endl;
    }
    system("pause");
    return 0;
}

NC13882_E-捡贝壳

题目描述

小明来到一片海滩上,他很喜欢捡贝壳,但他只喜欢质量为x的倍数的贝壳。 贝壳被排列成一条直线,下标从1到n编号,小明打算从编号为区间[l,r]的贝壳中,捡起所有他喜欢的贝壳。你能帮他计算出他能捡多少贝壳吗。 给出一个大小为n(n≤105)的数组,下标从1到n编号,a1,a2,...ana_1,a_2,...a_na1,a2,...an。a_i表示贝壳的质量。 给出q(q≤5∗104)次询问,每次询问包含3个整数l,r,x(1≤l≤r≤n,1≤x≤105)l每次询问,输出一行整数,表示这次询问中能捡到的贝壳数。

第一行给出两个整数n和q,含义如上所示。第二行给出n个整数表示a1,a2,...ana_1,a_2,...a_na1,a2,...an。接下来q行,每行3个整数l,r,x,含义如上所示。对于每次询问输出该次询问中能捡到的贝壳数

测试样例

样例1

输入

5 3
1 2 3 4 5
1 3 2
1 5 3
2 5 4

输出

1
1
1

样例2

输入

10 3
5532 24380 19363 11022 23965 22383 27049 22357 30453 7451
1 6 2
3 10 10
1 10 9

输出

3
0
1

解题思路

直接枚举+桶排序绝对超时,需要使用vec进行分块,具体思路见注释。灵活使用lower_bound和upper_bound函数进行统计。

解题代码

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e5 + 10;

vector<int> vec[maxn];
signed main()
{
    ios::sync_with_stdio(false), cin.tie(0);
    int n, q;
    cin >> n >> q;
    int big = 0;
    for (int i = 1; i <= n; ++i)
    {
        int p;
        cin >> p;
        big = max(big, p);
        //将质量为p的贝壳的键值压入p容器,所以vec[p]存放的是所有质量为p的贝壳键值
        vec[p].push_back(i);
    }
    while (q--)
    {
        int l, r, x;
        cin >> l >> r >> x;
        int ans = 0;
        //枚举x的倍数的质量的贝壳
        for (int i = x; i <= big; i += x)
        {
            //大于等于质量为i的键值
            int zuo = lower_bound(vec[i].begin(), vec[i].end(), l) - vec[i].begin();
            //大于质量为i的键值
            int you = upper_bound(vec[i].begin(), vec[i].end(), r) - vec[i].begin();
            //相见就是所有质量为i的贝壳的数量
            ans += you - zuo;
        }
        cout << ans << endl;
    }
    system("pause");
    return 0;
}
全部评论

相关推荐

点赞 收藏 评论
分享
牛客网
牛客企业服务