题目如下:
理解题意:n个人m个窗口,最多100个窗口,剔除掉所有数字为窗口数字ai倍数的人。
1.输入n、m,循环输入每个窗口中的数字,用数组a存放。
2.从1开始循环判断每一个人
3.嵌套循环对是否需要带出队伍进行判断
4.输出剩下的人数
注:该方法暴力枚举,时间复杂度为O(n*m)
实现代码如下:
#include <bits/stdc++.h>
using namespace std;
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
int n, m;//n个人,m个窗口
int a[100];//最大100个ai
cin >> n >> m;
for (int i = 0; i < m; i++)//输入数据
cin >> a[i];
int number = 0;//需要带出队伍的人数
for (int i = 1; i <= n; i++)//对每一个数循环判断
{
int flag = 0;//标志变量,为1则带出队伍
for (int j = 0; j < m; j++)//对是否为每个窗口进行判断
if (i % a[j] == 0)//如果是ai倍数则标志变量置1
flag = 1;
if (flag)//如果标志变量为1则带出队伍的人数加一
number++;
}
cout << n - number;//输出队伍中还剩下的人数
return 0;
}
//排队问题,暴力枚举,时间复杂度O(n*m)
但是最长耗时居然达到了27ms,这让我觉得很不可思议,于是我找到了大佬的0ms代码
如下:
#include <cstdio>
#include <algorithm>
#include <vector>
#include <queue>
using namespace std;
int a[105];
bool out[100005];
int main()
{
int n, m;
scanf("%d%d", &n, &m);
for (int i = 0; i < m; i++)
{
scanf("%d", &a[i]);
}
int ans = n;
for (int i = 0; i < m; i++)
{
for (int j = 1; a[i] * j <= n; j++)
{
if (!out[a[i] * j])
{
out[a[i] * j] = true;
ans--;
}
}
}
printf("%d", ans);
return 0;
}
cin、scanf和头文件对耗时的影响很小,我发现关键还是出在我的算法上。
大佬的思路是:
1.先用bool存好n个false
2.对于每一个窗口的数,用j表示倍数,循环结束条件为a[i] * j <= n,然后要剔除的位置赋值为true,总数减一
注:bool类型为全局变量时默认为false
题外话:对于数据不太大的情况我们用最大数的数组,测试未通过才用new分配内存空间。(我发现在本题中用new的时间比数组更长,达到了33ms)
最终代码:
#include <bits/stdc++.h>
using namespace std;
bool que[100000];
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
int n, m;//n个人,m个窗口
int a[100];//最大100个ai
cin >> n >> m;
for (int i = 0; i < m; i++)//输入数据
cin >> a[i];
int num = n;//队伍中的人数
for (int i = 0; i < m; i++)//对每一个窗口数的倍数进行剔除
for (int j = 1; a[i] * j <= n; j++)//j为倍数,找到n中所有的当前窗口数的倍数
if (!que[a[i] * j])//只要que数组当前位置的值为false
{
que[a[i] * j] = true;//给当前却que数组的位置赋值true,用以判断,避免重复计算
num--;//剔除当前位置的人
}
cout << num;//输出队伍中还剩下的人数
return 0;
}
时间优化到了最多耗时1ms,达到了我理想的效果。
扫描二维码关注公众号,回复:
11430384 查看本文章