C语言在一个有限的正整数序列中,【JLU数据结构荣誉课】第一次上机实验

7-1 重复计数 (100 分)

代码长度限制 \(16 KB\)

时间限制 \(1000 ms\)

内存限制 \(64 MB\)

Description

在一个有限的正整数序列中,有些数会多次重复出现。请你统计每个数的出现次数,然后按数字在序列中第一次出现的位置顺序输出数及其次数。

Input

第1行,1个整数 \(N\) ,表示整数的个数,\((1≤N≤50000)\)。

第2行,\(N\) 个正整数,每个整数 \(x\) 都满足 \(1 ≤ x ≤2000000000\)。

Output

若干行,每行两个用一个空格隔开的数,第一个是数列中出现的数,第二个是该数在序列中出现的次数。

Sample Input

12

8 2 8 2 2 11 1 1 8 1 13 13

Sample Output

8 3

2 3

11 1

1 3

13 2

思路

map裸题,将出现多少个数用 \(tot\) 和 \(b\) 数组记录有多少个数出现,用map记录每个数出现的次数即可。

代码

#include

#include

#include

#include

#include

#include

#include

#include

#define rg register

#define ll long long

using namespace std;

inline ll read(){

rg ll f = 0, x = 0;

rg char ch = getchar();

while(!isdigit(ch))f |= (ch == '-'), ch = getchar();

while( isdigit(ch))x = (x << 1) + (x << 3) + (ch ^ 48), ch = getchar();

return f? -x: x;

}

ll b[50010];

int tot = 0;

map mp;

int main(){

ll n = read();

ll a[50010];

for(rg int i = 1; i <= n; ++i){

ll tmp = read();

if(!mp[tmp]){

b[++tot] = tmp;

mp[tmp]++;

} elsemp[tmp]++;

}

for(rg int i = 1; i <= tot; ++i){

printf("%lld %lld\n", b[i], mp[b[i]]);

}

return 0;

}

7-2 报数游戏 (100 分)

代码长度限制 \(16 KB\)

时间限制 \(400 ms\)

内存限制 \(64 MB\)

Description

\(n\) 个人围成一圈,从 \(1\) 开始依次编号,做报数游戏。 现指定从第 \(1\) 个人开始报数,报数到第 \(m\) 个人时,该人出圈,然后从其下一个人重新开始报数,仍是报数到第 \(m\) 个人出圈,如此重复下去,直到所有人都出圈。总人数不足 \(m\) 时将循环报数。请输出所有人出圈的顺序。

Input

一行,两个整数 \(n\) 和 \(m\) 。\(n\) 表示游戏的人数,\(m\) 表示报数出圈的数字,\(1≤n≤50000\),\(1≤m≤100\).

Output

一行,\(n\) 个用空格分隔的整数,表示所有人出圈的顺序

Sample Input

5 2

Sample Output

2 4 1 5 3

思路

经典约瑟夫问题,不多解释

代码

#include

#include

#include

#include

#include

#include

#include

#define rg register

#define ll long long

using namespace std;

inline int read(){

rg int f = 0, x = 0;

rg char ch = getchar();

while(!isdigit(ch))f |= (ch == '-'), ch = getchar();

while( isdigit(ch))x = (x << 1) + (x << 3) + (ch ^ 48), ch = getchar();

return f? -x: x;

}

int main(){

int n = read(), m = read();

int a[50010] = {0}, cnt = n, ind = 1, num = 1;

while(cnt){

if(ind == n + 1)ind = 1;

if(a[ind]){

ind ++;

continue;

}

if(num == m){

a[ind] = 1;

printf("%d", ind);

num = 1;

cnt --;

if(cnt)printf(" ");

}

else{

num ++;

}

ind ++;

}

return 0;

}

7-3 算术表达式计算 (100 分)

代码长度限制 \(16 KB\)

时间限制 \(400 ms\)

内存限制 \(64 MB\)

Description

任务: 计算算术表达式的值。

算术表达式按中缀给出,以 \(=\) 号结束,包括 \(+,-,\times,\div\) 四种运算和 \((\)、\()\) 分隔符。运算数的范围是非负整数,没有正负符号,小于等于 \(10^{9}\)。

计算过程中,如果出现除数为0的情况,表达式的结果为”NaN” ; 如果中间结果超出32位有符号整型范围,仍按整型计算,不必特殊处理。 输入保证表达式正确。

Input

一行,包括1个算术表达式。算术表达式的长度小于等于 \(1000\)。

Output

一行,算术表达式的值 。

Sample Input

(1+30)/3=

Sample Output

10

思路

用一个栈来存符号,另一个栈来存数字。如果是数字直接入数字栈;如果是符号,栈空则立刻入栈,是左括号立刻入栈,优先级大于上一个字符入栈,是右括号则一直弹栈运算到弹出左括号,如果优先级小于等于上一个字符,则一直运算弹栈到左括号或栈空。要特别注意优先级的判断与不合法情况的判断(除数不为0)。详情见代码。

代码

#include

#include

#include

#include

#include

#include

#include

using namespace std;

inline bool judpri(char a, char b){

if((a == '*' || a == '/') && (b == '+' || b == '-'))return 1;

if((a == '+' || a == '-') && (b == '+' || b == '-'))return 0;

if((a == '+' || a == '-') && (b == '*' || b == '/'))return 0;

if((a == '*' || a == '/') && (b == '*' || b == '/'))return 0;

return 1;

}

inline int cal(int n1, char opt, int n2){

if(opt == '+')return n1 + n2;

if(opt == '-')return n1 - n2;

if(opt == '*')return n1 * n2;

if(opt == '/')return n1 / n2;

}

inline bool judcal(char opt, int num){

if(opt == '/' && num == 0)return 0;

elsereturn 1;

}

int main(){

char ch;

int Q[10100];//num

int qtop = 0;

char C[10100];//opt

int ctop = 0;

int book = 0;

scanf("%c", &ch);

if(ch == '=')book = 1;

//cout << ch<

while(!book){

//cout << ch << endl;

int num[20], tot = 0;

int sum = 0;

while(ch >= '0' && ch <= '9'){

//cout << ch<

num[++ tot] = ch - '0';

scanf("%c", &ch);

if(ch == '=')book = 1;

}

if(tot){

for(int i = 1; i <= tot; ++i){

sum = sum * 10 + num[i];

}

Q[++qtop] = sum;

//cout << sum << endl;

continue;

}

//cout << ch << endl;

if(ch == ')'){

while(C[ctop] != '(' && ctop){

int n2 = Q[qtop --], c = C[ctop --], n1 = Q[qtop --];

//cout << n1 << ' ' << c << ' ' << n2 << endl;

if(!judcal(c, n2)){

printf("NaN");

return 0;

}

int ans = cal(n1, c, n2);

Q[++qtop] = ans;

}

ctop --;

} else if(ch == '(' || !ctop || judpri(ch, C[ctop])){

C[++ctop] = ch;

//putchar(ch);

} else{

while(ctop && C[ctop] != '('){

int n2 = Q[qtop --], c = C[ctop], n1 = Q[qtop --];

//cout << n1 << ' ' << c << ' ' << n2 << endl;

if(!judcal(c, n2)){

printf("NaN");

return 0;

}

int ans = cal(n1, c, n2);

Q[++qtop] = ans;

ctop --;

}

C[++ctop] = ch;

}

scanf("%c", &ch);

if(ch == '=')book = 1;

//cout << ch<

}

while(ctop){

int n2 = Q[qtop --], c = C[ctop], n1 = Q[qtop --];

if(!judcal(c, n2)){

printf("NaN");

return 0;

}

int ans = cal(n1, c, n2);

Q[++qtop] = ans;

ctop --;

}

printf("%d", Q[1]);

return 0;

}

//(((1+2)/(1+1-1)/3)*2/2/2)+1)+1=

7-4 最喜爱的序列 (100 分)

代码长度限制 \(16 KB\)

时间限制 \(400 ms\)

内存限制 \(64 MB\)

Description

小唐这段时间在研究序列。拿来 \(n\) 个整数的序列,他给序列中的每个整数都赋予一个喜爱值。喜爱值也是整数,有正有负,越大表明越喜欢。他想知道,如何从序列中连续取最多 \(m\) 个数,他获得喜爱值最大。\(1≤n≤500000\),\(1≤m≤N\)。

Input

第一行是两个整数 \(n\), \(m\) 。分别代表序列中数的个数以及能取的最多个数。

第二行用空格隔开的 \(n\) 个整数,第 \(i\) 个整数 \(Li\) 代表他对第 \(i\) 个数的喜爱值。\(│Li│≤1000\)

Output

一行,三个数,表示获得最大喜爱值,及第一个取最大喜爱值的区间。

Sample Input

5 2

1 4 5 2 3

Sample Output

9 2 3

思路

单调队列。处理一个前缀和,单调队列中存左端点,保持从1到左端点的和单调递增,当超过区间距离时出队,每次以队头点到当前端点的区间和与答案比较,更新答案即可。

代码

#include

#include

#include

#include

#include

#include

#include

#define rg register

#define ll long long

using namespace std;

inline int read(){

rg int f = 0, x = 0;

rg char ch = getchar();

while(!isdigit(ch))f |= (ch == '-'), ch = getchar();

while( isdigit(ch))x = (x << 1) + (x << 3) + (ch ^ 48), ch = getchar();

return f? -x: x;

}

const int inf = 0x7fffffff;

int q[500010], maxn, ml, mr;

int sum[500010];

int main(){

int n = read(), m = read();

sum[0] = 0;

int f = 0, r = -1;

maxn = -inf;

for(rg int i = 1; i <= n; ++i){

sum[i] = sum[i - 1] + read();

}

for(rg int i = 1; i <= n; ++i){

while(f <= r && q[f] < i - m)f++;

if(maxn < sum[i] - sum[q[f]]){

maxn = sum[i] - sum[q[f]];

ml = q[f] + 1;

mr = i;

}

while(f <= r && sum[q[r]] >= sum[i])r--;

q[++r] = i;

}

printf("%d %d %d", maxn, ml, mr);

return 0;

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值