枚举专题练习

问题 AT: 【枚举】桐桐的深入研究(未解决)

** 题目描述**

两个数的最大公约数与最小公倍数的问题解决了,桐桐又进行了进一步的研究。她发现求n个正整数的最大公约数与最小公倍数要复杂一些,你能帮助她解决这个问题吗?

** 输入**

第1行一个数n(2≤n≤100),表示一共n个正整数;第2行有n个正整数,相邻的数用空格隔开,每个数不超过30000。

** 输出**

第1行一个数,表示n个正整数的最大公约数;第2行一个数,表示n个正整数的最小公倍数。答案保证不超过长整型。

** 样例**

样例输入
3
3 4 5
样例输出
1

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

ll gcd(ll a, ll b) {
    ll c = a % b;
    while (c) {
        a = b;
        b = c;
        c = a % b;
    }
    return b;
}
ll n, a[105], gys = 1, gbs;
signed main() {
    ios::sync_with_stdio(false);
    cin.tie(), cout.tie();
    cin >> n;
    for (int i = 0; i < n; i++)cin >> a[i];
    gys = gcd(a[0], a[1]);
    for (int i = 1; i < n; i++) {
        gys = gcd(a[i], gys);
    }
    cout << gys << endl;
    gbs = a[0] / gcd(a[0], a[1]) * a[1];
    for (int i = 2; i < n; i++) {
        gbs = gbs * gcd(gbs, a[i]) * a[i];
    }
    cout << gbs << endl;
}

问题 AZ: 【枚举】城市路站

题目描述

在这里插入图片描述
在A,B两个城市之间设有N个路站(如图中的S1,且N≤10),城市与路站之间、路站和路站之间各有若干条路段(各路段数≤10,且每条路段上的距离均为一个整数)。A,B的一条通路是指:从A出发,可经过任一路段到达S1,再从S1出发经过任一路段……最后到达B。通路上路段距离之和称为通路距离(最大距离≤1000)。当所有的路段距离给出之后,求出所有不同距离的通路个数(相同距离仅记一次)。例如,上图所示是当N=I时的情况。
从A到B的通路条数为6,但因其中通路5+5=4+6,所以满足条件的不同距离的通路条数为5。

** 输入**

第1行:一个整数N(1≤N≤10),表示路站的数量。
接下来N+1组,每组第一行为一个整数ki(1≤ki≤10),表示到达当前路站或城市的路段数;接下来ki行,每行一个整数wij,表示每一条路段的距离。
输出
一个整数,从A到B所有不同距离的通路个数。
样例
样例输入
1
3
5
7
4
2
6
5
样例输出
5

思路
用数组a存储到站台前的一个城镇的距离状态,数组b存储到站台后的一个城镇的距离状态,最后再遍历a数组的距离状态便可得出结果

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
int n, x, num, a[1005], b[1005];
int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr), cout.tie(nullptr);
    cin >> n;
    cin >> x;
    for (int i = 0; i < x; i++) {
        cin >> num;
        a[num] = 1;
    }
    while (n--) {
        cin >> x;
        for (int i = 0; i < x; i++) {
            cin >> num;
            for (int j = 0; j <= 1000; j++) {
                if (a[j]) {
                    b[j + num] = 1;
                }
            }
        }
        for (int i = 0; i <= 1000; i++) {
            a[i] = b[i];
        }
        fill(b, b + 1000, 0);
    }
    int sum = 0;
    for (int i = 0; i <= 1000; i++) {
        sum += a[i];
    }
    cout << sum;
}

问题 BM: Box and Ball

题目描述

We have N boxes, numbered 1 through N. At first, box 1 contains one red ball, and each of the other boxes contains one white ball.
Snuke will perform the following M operations, one by one. In the i-th operation, he randomly picks one ball from box xi, then he puts it into box yi.
Find the number of boxes that may contain the red ball after all operations are performed.
Constraints
2≤N≤105
1≤M≤105
1≤xi,yi≤N
xi≠yi
Just before the i-th operation is performed, box xi contains at least 1 ball.
题目大意
我们有N个盒子,编号从1到N。首先,盒子1包含一个红球,其他每个盒子包含一个白球。
Snuke将一个接一个地执行以下M个操作。在第i个操作中,他随机从盒子xi中取出一个球,然后把它放入盒子yi中。
在所有操作完成后,找出可能包含红球的方块数目。

测试样例

样例输入
3 2
1 2
2 3
样例输出
2

提示

第一次操作之后,盒子1是空的,盒子2包含一个红球和一个白球,盒子3包含一个白球。现在,考虑第二个操作。如果斯纳克从2号盒子里选出红球,红球就会进入3号盒子。如果他选择白球,红球将留在方格2。因此,在所有操作之后,可能包含红球的盒子的数量为2。

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

int x[101011],y[101011],tal[101011],flag[101011];
int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr), cout.tie(nullptr);
    int n, m;
    cin >> n >> m;
    for (int i = 1; i <= n; i++) {
        tal[i] = 1;
    }
    for (int i = 1; i <= m; i++) {
        cin >> x[i] >> y[i];
    }
    flag[1] = 1;
    for (int i = 1; i <= m; i++) {
        tal[x[i]]--;
        tal[y[i]]++;
        if (flag[x[i]])
            flag[y[i]] = 1;
        if (tal[x[i]] == 0)
            flag[x[i]] = 0;
    }
    int count1 = 0;
    for (int i = 1; i <= n; i++) {
        if (flag[i]) {
            count1++;
        }
    }
    cout << count1 << endl;
}

问题 N: Bessie Slows Down(代码正确,但不懂思路)

题目描述

Bessie the cow is competing in a cross-country skiing event at the winter Moolympic games. She starts out at a speed of 1 meter per second. However, as she becomes more tired over time, she begins to slow down. Each time Bessie slows down, her speed decreases: she moves at 1/2 meter per second after slowing down once, then 1/3 meter per second after slowing down twice, and so on.You are told when and where Bessie slows down, in terms of a series of events. An event like this:T 17
means that Bessie slows down at a specific time – here, 17 seconds into the race. An event like this:D 10
means that Bessie slows down at a specific distance from the start – in this case, 10 meters.
Given a list of N such events (1 <= N <= 10,000), please compute the amount of time, in seconds, for Bessie to travel an entire kilometer. Round your answer to the nearest integer second (0.5 rounds up to 1).
题目大意
奶牛贝西正在参加冬季奥林匹克运动会的越野滑雪比赛。它以1m / s的速度开始。然而,随着时间的推移,她变得越来越累,她开始放慢速度。贝西每减速一次,速度就会降低:减速一次后速度为每秒1/2米,减速两次后速度为每秒1/3米,以此类推。通过一系列事件,你会知道贝西在何时何地放慢了速度。像这样的事件:T 17意味着贝西会在一个特定的时间放慢速度——在这里,比赛开始17秒。D 10意味着贝西在距离开始一定距离处减速——在这个例子中是10米。给定N个这样的事件(1 <= N <= 10,000),请计算贝西移动一公里所需的时间,单位为秒。将你的答案四舍五入到最接近的整数秒(0.5四舍五入到1)。

样例

样例输入
2
T 30
D 10
样例输出
2970

提示

Bessie slows down at time t = 30 and at distance d = 10.Bessie travels the first 10 meters at 1 meter/second, taking 10 seconds. She then slows down to 1/2 meter/second, taking 20 seconds to travel the next 10 meters. She then reaches the 30 second mark, where she slows down again to 1/3 meter/second. The remaining 980 meters therefore take her 980 * 3 = 2940 seconds. The total time is therefore 10 + 20 + 2940 = 2970.

#include<bits/stdc++.h>
using namespace std;
#define maxn 20005
double t[maxn],d[maxn],nowt;
int curt,curd,n,speed=1,cpt=1;
int main() {
    cin >> n;
    char ch;
    double x;
    for (int i = 1; i <= n; i++) {
        cin >> ch;
        cin >> x;
        if (ch == 'T') t[++curt] = x;
        else d[++curd] = x;
    }
    d[++curd] = 0;
    d[++curd] = 1000;
    sort(d + 1, d + curd + 1);
    sort(t + 1, t + curt + 1);
    for (int i = 1; i < curd; i++) {
        double nowdis = d[i];
        while (nowdis < d[i + 1] && cpt <= curt &&
               nowt + (d[i + 1] - nowdis) * speed > t[cpt]) {
            nowdis += (t[cpt] - nowt) / speed;
            speed++;
            nowt = t[cpt++];
        }
        nowt += (d[i + 1] - nowdis) * speed;
        speed++;
    }
    if (nowt - (int) nowt > 0.5) nowt = (int) nowt + 1;
    else nowt = (int) nowt;
    printf("%.0lf\n", nowt);
}

问题 CV: 粉兔搭方块

题目描述

粉兔迷上了搭方块!粉兔有一个 N 行 M 列的网格。现在,她从 nzhtl1477 那里抢到了 K 个长方形的方块 。第 i 个积木的宽为 Wi格,高为 Hi格。粉兔从网格的顶端依次扔下这 K 个方块,来满足她那不可描述的破坏欲。每个方块均竖直下落,并且第 i 个方块的左端与网格第 Ci列的左端在同一直线上。如果方块在下落的过程中底部碰到了网格底部或另一个方块的顶部,那么这个方块就会立刻被固定住。如果一个方块被固定住时顶部高于网格顶端,那么粉兔就会非常生气,以至于她把整个网格图都砸烂(当然,后面的方块也就不能被扔下了)。粉兔已经定好了她的破坏计划,你的任务就是求出网格图最终的样子。

输入

第一行包含三个正整数 N,M 和 K。
接下来 K 行,每行三个正整数 Wi,Hi和 Ci。

输出

如果网格图没有被砸烂,你的程序应该输出网格图最终的样子,用 # 表示 方块,. 表示空缺 。也就是说,输出应当有 N 行,每行为一个长度 M 的只包含 # 和 . 的字符串。否则的话,你的程序应当输出两行。第一行为 PinkRabbit is ANGRY!!!,第二行为一个整数,表示粉兔扔下的方块数目(包括超出网格顶部的那个)。

样例

样例输入
4 3 2
1 2 2
2 1 2
样例输出

.##
.#.
.#.

提示

第一个方块宽为 1,高为 2,落下后,网格如下 :


.#.
.#.
第二个方块宽为 2,高为 1,落到如图所示位置后即停下。

.##
.#.
.#.
子任务 1:N,M≤10,K≤5;
子任务 2:N,M≤50,K≤10;
子任务 3:Wi=1;
子任务 4:Hi=1;
子任务 5:无特殊性质。
对于 100%的数据, 1≤N,M,K≤250,1≤Wi≤M,1≤Hi≤N, 1≤Ci≤M−Wi+1。

思考题:如果只需要输出每个方块最终的位置而不整网格,是否有 O((N+K)log2N)做法?

思路:直接暴力就完了;

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

int n, m, k, h, w, c, f, cont ;
int main() {
    ios::sync_with_stdio(false);
    cin.tie(), cout.tie();
    cin >> n >> m >> k;
    char str[1000][1000];
    for (int i = 0; i <= n; i++)
        for (int j = 0; j <= m; j++)
            if (i == n)str[i][j] = '#';
            else str[i][j] = '.';
    for (int i = 0; i < k; i++) {
        cin >> w >> h >> c;
        cont++;
        c--;
        int s = 0;
        for (int j = 0; j < n; j++) {
            for (int l = c; l < c + w; l++)
                if (str[j + 1][l] == '#') {
                    s = j;
                    break;
                }
            if (s)break;
        }
        if (s - h < 0) {
            f = 1;
            break;
        }
        for (int j = s; j > s - h; j--)
            for (int l = c; l < c + w; l++)
                str[j][l] = '#';
    }
    if (f == 1) {
        cout << "PinkRabbit is ANGRY!!!" << endl << cont << endl;
    } else {
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                cout << str[i][j];
            }
            if (i != n - 1)cout << endl;
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值