本部分总题单如下
【腾讯文档】副本-CSP-JS+NOI 题单 (未完待续)
https://docs.qq.com/sheet/DSmJuVXR4RUNVWWhW?tab=BB08J2
https://www.luogu.com.cn/problem/P1996
n n n 个人围成一圈,从第一个人开始报数,数到 m m m 的人出列,再由下一个人重新从 1 1 1 开始报数,数到 m m m 的人再出圈,依次类推,直到所有的人都出圈,请输出依次出圈人的编号。
注意:本题和《深入浅出-基础篇》上例题的表述稍有不同。书上表述是给出淘汰 n − 1 n-1 n−1 名小朋友,而该题是全部出圈。
输入两个整数 n , m n,m n,m 。
输出一行 n n n 个整数,按顺序输出每个出圈人的编号。
10 3
3 6 9 2 7 1 8 5 10 4
1 ≤ m , n ≤ 100 1 \le m, n \le 100 1≤m,n≤100
#include
#include
#include
using namespace std;
queue<int> q;// 队列q 存储每个人
int main()
{
// n个人 数到m,这个人就退出
int n,m;
// e表示开始查的数
int e=1;
cin>>n>>m;
for(int i=1;i<=n;i++)
{
q.push(i);//模拟队列 把1到n个人插入到队列中
}
// 如果队列不为空
while(!q.empty())
{
// 如果开始查的数e与m相等
if(e==m)//如果这个人正好被踢
{
cout<<q.front()<<" ";//先输出队列队首
q.pop();//再删除队首
e=1;//再从1开始报数
}
// 如果开始查的数e与m不相等
else if(e!=m)//如果不被剔除
{
e++;//报的数+1
q.push(q.front());//先把head压进队尾
q.pop();//再把head删除
}
}
return 0;//结束程序(完美)
}
#include
using namespace std;
int main()
{
int n,m,s=0; // s表示当前人的序号从1到n n表示总人数 m表示数到m就出队
scanf("%d%d",&n,&m);//入读
bool visit[200]={0};//visit赋初始值
for(int k=0;k<n;k++){//总共要出队n次
for(int i=0;i<m;i++){ //每次出队后都重1开始查数
if(++s>n)s=1;// 如果s大于n表示喊道了最后一位,s设置为1
if(visit[s])i--; //如果队列visit[s]为true 则表示该用户已经出队了 执行i--
}//类似取模,而因为序列是从1开始的,所以不取模,加判断;若visit过,则i--,使其继续循环
printf("%d ",s);// 循环结束后 输出序号s
visit[s]=true;//输出,记录s已出队
}
return 0;
}
https://www.luogu.com.cn/problem/P5661
著名旅游城市 B 市为了鼓励大家采用公共交通方式出行,推出了一种地铁换乘公交车的优惠方案:
现在你得到了小轩最近的公共交通出行记录,你能帮他算算他的花费吗?
输入文件的第一行包含一个正整数 n n n ,代表乘车记录的数量。
接下来的 n n n 行,每行包含 3 个整数,相邻两数之间以一个空格分隔。第 i i i 行的第 1 个整数代表第 i i i 条记录乘坐的交通工具,0 代表地铁,1 代表公交车;第 2 个整数代表第 i i i 条记录乘车的票价 p r i c e i price_i pricei ;第三个整数代表第 i i i 条记录开始乘车的时间 t i t_i ti (距 0 时刻的分钟数)。
我们保证出行记录是按照开始乘车的时间顺序给出的,且不会有两次乘车记录出现在同一分钟。
输出文件有一行,包含一个正整数,代表小轩出行的总花费。
6
0 10 3
1 5 46
0 12 50
1 3 96
0 5 110
1 6 135
36
6
0 5 1
0 20 16
0 7 23
1 18 31
1 4 38
1 7 68
32
样例 1 说明
第一条记录,在第 3 分钟花费 10 元乘坐地铁。
第二条记录,在第 46 分钟乘坐公交车,可以使用第一条记录中乘坐地铁获得的优惠票,因此没有花费。
第三条记录,在第 50 分钟花费 12 元乘坐地铁。
第四条记录,在第 96 分钟乘坐公交车,由于距离第三条记录中乘坐地铁已超过 45 分钟,所以优惠票已失效,花费 3 元乘坐公交车。
第五条记录,在第 110 分钟花费 5 元乘坐地铁。
第六条记录,在第 135 分钟乘坐公交车,由于此时手中只有第五条记录中乘坐地铁获得的优惠票有效,而本次公交车的票价为 6 元,高于第五条记录中地铁的票价 5 元,所以不能使用优惠票,花费 6 元乘坐公交车。
总共花费 36 元。
样例 2 说明
第一条记录,在第 1 分钟花费 5 元乘坐地铁。
第二条记录,在第 16 分钟花费 20 元乘坐地铁。
第三条记录,在第 23 分钟花费 7 元乘坐地铁。
第四条记录,在第 31 分钟乘坐公交车,此时只有第二条记录中乘坐的地铁票价高于本次公交车票价,所以使用第二条记录中乘坐地铁获得的优惠票。
第五条记录,在第 38 分钟乘坐公交车,此时第一条和第三条记录中乘坐地铁获得的优惠票都可以使用,使用获得最早的优惠票,即第一条记录中乘坐地铁获得的优惠票。
第六条记录,在第 68 分钟乘坐公交车,使用第三条记录中乘坐地铁获得的优惠票。
总共花费 32 元。
数据规模与约定
对于 30 % 30\% 30% 的数据, n ≤ 1000 n \leq 1000 n≤1000, t i ≤ 1 0 6 t_i \leq 10^6 ti≤106 。
另有 15 % 15\% 15% 的数据, t i ≤ 1 0 7 t_i \leq 10^7 ti≤107 ,所有 p r i c e i price_i pricei 相等。
另有 15 % 15\% 15% 的数据, t i ≤ 1 0 9 t_i \leq 10^9 ti≤109 ,所有 p r i c e i price_i pricei 相等。
对于 100 % 100\% 100% 的数据, n ≤ 1 0 5 n \leq 10^5 n≤105 , t i ≤ 1 0 9 t_i \leq 10^9 ti≤109 , 1 ≤ p r i c e i ≤ 1000 1 \leq price_i \leq 1000 1≤pricei≤1000 。
#include
using namespace std;
const int MAXN = 100005;
struct Ticket {
//赠票的价格,最晚使用时间和是否需用过
int price, time, used;
} q[MAXN];//赠票盒子
int head, tail, n, cost;
int main() {
cin >> n;
for (int i = 0; i < n; ++i) {
int op, price, time;
//输入每次坐车的种类,价格和发车时间
cin >> op >> price >> time;
if (op == 0) {
//如果是坐地铁,直接把价格加到cost里面
cost += price;
//新一张赠票插入数组末尾,这张票的最晚使用时间是当前时间+45
q[tail].time = time + 45;
//赠票面额就是地铁票价
q[tail++].price = price;
} else {
//先用一个循环把过期票扔掉
while (head < tail && q[head].time < time) {
head++;
}
bool found = false;//表示是否有合适的赠票,先假设没有
for (int j = head; j < tail; ++j) {
//循环所有剩余的票,这些一定都没过期,因为题目中时间是按顺序给我们的
if (q[j].price >= price && q[j].used == 0) {
//如果价格合适,并且没用过,标记找到了,这张票标记用过
found = true;
q[j].used = 1;
break;
}
}
//如果没找到合适的赠票,老老实实花钱买吧
if (!found) cost += price;
}
}
cout << cost << endl;
return 0;
}