XUPT 寒假算法集训第二周

A - 金银岛

某天KID利用飞行器飞到了一个金银岛上,上面有许多珍贵的金属,KID虽然更喜欢各种宝石的艺术品,可是也不拒绝这样珍贵的金属。但是他只带着一个口袋,口袋至多只能装重量为w的物品。岛上金属有s个种类, 每种金属重量不同,分别为n1, n2, ... , ns,同时每个种类的金属总的价值也不同,分别为v1,v2, ..., vs。KID想一次带走价值尽可能多的金属,问他最多能带走价值多少的金属。注意到金属是可以被任意分割的,并且金属的价值和其重量成正比。

Input

第1行是测试数据的组数k,后面跟着k组输入。

每组测试数据占3行,第1行是一个正整数w (1 <= w <= 10000),表示口袋承重上限。第2行是一个正整数s (1 <= s <=100),表示金属种类。第3行有2s个正整数,分别为n1, v1, n2, v2, ... , ns, vs分别为第一种,第二种,...,第s种金属的总重量和总价值(1 <= ni <= 10000, 1 <= vi <= 10000)。

Output

k行,每行输出对应一个输入。输出应精确到小数点后2位。

Sample

InputcopyOutputcopy
2
50
4
10 100 50 30 7 34 87 100
10000
5
1 43 43 323 35 45 43 54 87 43
171.93
508.00

 AC代码: 一直变化承重重量

#include<stdio.h>
#include<iostream>
#include<algorithm>
using namespace std;
struct Kid
{
	int n, v;
	double value;
}kid[10005];

bool cmp(Kid a, Kid b)
{
	return a.value > b.value;
}
int main()
{
	int k;
	scanf("%d", &k);
	while (k--)
	{
		int  w, s;
		scanf("%d %d", &w, &s);
		for (int i = 0; i < s; i++)
		{
			scanf("%d %d", &kid[i].n, &kid[i].v);
			kid[i].value = kid[i].v*1.0 / kid[i].n;
		}
		sort(kid, kid + s, cmp);
		double sum = 0;
		for (int j = 0; j < s; j++)
		{
			if (kid[j].n < w)
			{
				w -= kid[j].n; //每次都要变化承重上限 
				sum += kid[j].v;
			}
			else
			{
				sum += w * kid[j].value;//最后所能承受的重量
				break;
			}
		}
		printf("%.2lf\n", sum);

	}
	return 0;
}

 还有一种方法: 承重不变, 测试数据都过了, 但是提交一直wrong answer

#include<stdio.h>
#include<iostream>
#include<algorithm>
using namespace std;
struct Kid
{
	int n, v;
	double value;
}kid[10005];
bool cmp(Kid a, Kid b)
{
	return a.value > b.value;
}
int main()
{
	int k;
	scanf("%d", &k);
	while (k--)
	{
		int  w, s;
		scanf("%d %d", &w, &s);
		for (int i = 0; i < s; i++)
		{
			scanf("%d %d", &kid[i].n, &kid[i].v);
			kid[i].value = kid[i].v*1.0 / kid[i].n;
		}
		sort(kid, kid + s, cmp);
		double sum = 0.0;
		int vei = 0;
		for (int j = 0; j < s; j++)
		{
			if (vei < w)
			{
				sum += kid[j].v;
				vei += kid[j].n; //记录现在承重总重量
				
			}
			else
			{
				vei -= kid[j-1].n;
				vei = w - vei;
				sum = sum - kid[j-1].v + vei * kid[j-1].value;
				break;
			}
		}
		printf("%.2lf\n", sum);

	}
	return 0;
}

B - USACO Number Triangles

题目描述

考虑在下面被显示的数字金字塔。

写一个程序来计算从最高点开始在底部任意处结束的路径经过数字的和的最大。

每一步可以走到左下方的点也可以到达右下方的点。

7

3 8

8 1 0

2 7 4 4

 4 5 2 6 5

在上面的样例中,从 7 到 3 到 8 到 7 到 5 的路径产生了最大和:30

输入格式

第一个行包含 R(1≤R≤1,000),表示行的数目。

后面每行为这个数字金字塔特定行包含的整数。

所有的被供应的整数是非负的且不大于 100。

输出格式

单独的一行包含那个可能得到的最大的和。

Sample 1

InputcopyOutputcopy
5
7
3 8
8 1 0
2 7 4 4
4 5 2 6 5
30

可以在纸上画一个真正的金字塔, 可以发现, 由上一行到下一行, 可以是左下或右下, 即下一行或下一行的右边一个, 动态规划, 从最下一行开始找, 找到最优方案

#include<stdio.h>
int a[1005], b[1005][1005];
int max(int a, int b)
{
	return a > b ? a : b; //输出最大值
}
int main()
{
	int n;
	scanf("%d", &n);
	int i, j;
	for (i = 1; i <= n; i++)
	{
		for (j = 1; j < i + 1; j++) //控制一行读一个数,两行读两个数
		{
			scanf("%d", &b[i][j]);
		}
	}
	for (j = 1; j <= n; j++)
		a[j] = b[n][j]; //最后一行先赋值

	for (i = n - 1; i > 0; i--) //从倒数第二行向上找
	{
		for (j = 1; j <= i; j++) //
		{
			a[j] = max(a[j], a[j + 1]) + b[i][j]; //a[j]的值一直在变化, 保障一直是最优方案
		}
	}
	printf("%d", a[1]);
	return 0;
}

E - 机器人走方格

M * N的方格,一个机器人要从左上格子的正中央走到右下格子的正中央。它每步可以从一个格子正中央移动到相邻格子正中央,且只能向右或向下走。请问有多少种不同的走法?由于方法数量可能很大,只需要输出Mod 10^9 + 7的结果。

Input

第1行,2个数M,N,中间用空格隔开。(2 <= m,n <= 1000)

Output

输出走法的数量。 

Sample

InputcopyOutputcopy
2 3
3

一开始用深搜, 然后超时了

#include<stdio.h>
int a[1005][1005], flag[1005][1005], m, n;
long long cnt;
void dfs(int x, int y, int step) //深搜函数
{
	int tx, ty;
	int next[2][2] = { {0,1},{1,0} };
	if (x == m && y == n)
	{
		cnt++;
		return;
	}
	
	for (int i = 0; i < 2; i++)
	{
		tx = x + next[i][0];
		ty = y + next[i][1];
		if (tx<1 || ty<1 || tx>m || ty>n)
			continue;
		if (a[tx][ty] == 0 && flag[tx][ty] == 0)
		{
			flag[tx][ty] = 1;
			dfs(tx, ty, step + 1);
			flag[tx][ty] = 0;
		}
	}
	
	return;
}
int main()
{
	scanf("%d %d", &m, &n);
	flag[1][1] = 1;
	dfs(1, 1, 0);
	printf("%lld", cnt);
	return 0;
}

 之后写了一个简单的递归, 还是超时了

#include<stdio.h>
int m, n;
long long cnt;
int robot(int m,int n)
{
	if (m <= 1 || n <= 1) return 1;
	else return robot(m - 1, n) + robot(m, n - 1);
}
int main()
{
	scanf("%d %d", &m, &n);
	cnt = robot(m, n);
	printf("%lld", cnt);

	return 0;
}

查了一下, 发现要用到记忆化搜索(以空间换时间, 进行标记, 减少重复)

#include<stdio.h>
#define Mod 1000000007;
int m, n,a[1005][1005];
long long cnt;
int robot(int m,int n)
{
	if (a[m][n])
		return a[m][n]; //如果已经标记过了, 直接返回
	else if (m <= 1 || n <= 1)
	{
		a[m][n] = 1; //进行标记
		return a[m][n];
	}
	a[m][n]= (robot(m - 1, n) + robot(m, n - 1)) % Mod; 
	return a[m][n];
}
int main()
{
	scanf("%d %d", &m, &n);
	cnt = robot(m, n);
	printf("%lld", cnt);

	return 0;
}

G - Protecting the Flowers

应队种下的苹果树终于结果了!
应队开心地将苹果装入箱子,一共装了n(2 <= n <=10^5) 个箱子。
但是他遇到一个问题,他每次只能搬一个箱子回到仓库,但每个箱子i在原地时会被学姐小李要求每分钟收Di(1<=Di<=100)的钱。也就是每个箱子不在仓库或被搬运时,每个箱子i会被要求每分钟收Di的钱。每个箱子距离仓库有Ti分钟(1 <=Ti <=10^5)搬一个箱子需要2Ti的时间(因为从原地出发到仓库,再从仓库回来)。
应队回来到另外一个箱子不需要额外时间。

现在请你帮助应队,如何使自己花费最少的钱搬完所有箱子。

Input

第一行:整数N,

第二行到N+1行:每一行包含两个用空格隔开的整数,Ti和Di,代表当前箱子的到仓库时间和花费。

Output

第一行:一个整数,表示需要花费地最小数量。

Sample Input

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

Sample Output

86

Hint

应队按顺序搬走了6,2,3,4,1,5的箱子。当6号箱子搬走,应队花了24元。2号箱子搬走,花了28元。3号,4号,1号箱子搬走,分别花费了16,12和6元。当搬5号箱子时,已经不会有别的箱子需要收费,所以为0.总花费为24+28+16+12+6+0 = 86

 

要注意审题, 花最少的钱搬完所有箱子

一开始用前缀和来写的, 但是一直runtime error

#include<stdio.h>
#include<iostream>
#include<algorithm>
using namespace std;
struct flower
{
	int t, d;
	float x;
}flo[100005];
int cmp1(flower a, flower b)
{
	return a.x < b.x;
}
int cmp2(flower a, flower b)
{
	return a.d > b.d;
}
int main()
{
	int n, i, j, sum[10005] = { 0 };
	long long m = 0;
	scanf("%d", &n);
	for (i = 0; i < n; i++)
	{
		scanf("%d %d", &flo[i].t, &flo[i].d);
		flo[i].x = flo[i].t * 1.0 / flo[i].d;
	}

	sort(flo, flo + n, cmp2);
	for (i = n - 1; i >= 1; i--)
		sum[i] += sum[i + 1] + flo[i].d;

	for(i = 0; i < n - 1; i++)
		m += 2 * flo[i].t * sum[i + 1];
	printf("%lld", m);
	return 0;
}

 后来发现没必要, 就先进行排序, 然后把所有的收费加起来, 每次搬走一个就减去这个箱子的费用

#include<stdio.h>
#include<iostream>
#include<algorithm>
using namespace std;
struct flower
{
	int d, t;
	double x;
}flo[100005];
int cmp(flower a, flower b)
{
	return a.x < b.x;
}
int main()
{
	int n, i, sum = 0;
	long long m = 0;
	scanf("%d", &n);
	for (i = 0; i < n; i++)
	{
		scanf("%d %d", &flo[i].t, &flo[i].d);
		flo[i].x = flo[i].t / (flo[i].d * 1.0);
		sum += flo[i].d; //把所有的费用先加起来
	}
	sort(flo, flo + n, cmp);
	for (i = 0; i < n; i++)
	{
		sum -= flo[i].d; //先减去要搬走的箱子的费用, 因为搬走就不用收费了
		m += 2 * flo[i].t * sum; //搬运时间是一来回所以乘二, 再乘现在的费用
	}
	printf("%lld", m);
	return 0;
}

H - Tian Ji -- The Horse Racing

HJ最近迷上了一种赛马游戏,邀请你和他一起愉快的玩耍。HJ觉得只是单纯的赛马不够刺激,需要来点彩头。你如果赢了HJ,就能获得200元,当然,输了就要给HJ 200元,平局则不产生金钱交易。现在你通过|SAKURA|SC提前得知了HJ的马的实力,你需要计算出,你最多能赢得多少钱。

Input

多组输入,最多50组,当N为0时结束,不需要处理这组数据。
第一行一个N。(N <= 1000)
接下来N个数,代表你的马的战斗力。
接下来N个数,代表HJ的马的战斗力。

Output

输出你最多能赢得多少钱。(答案可能为负数)

Sample Input

3
92 83 71
95 87 74
2
20 20
20 20
2
20 19
22 18
0

Sample Output

200
0
0

首先对田忌的马和齐王的马的速度进行排序

1.如果田忌最快的马速 > 齐王最快的马速: 直接比掉 ,赢一局

2.如果田忌最快的马速 < 齐王最快的马速: 田忌必定输, 为把损失降到最小, 用田忌最慢的马与齐王最快的马比

3. .如果田忌最快的马速 == 齐王最快的马速: 再比较最慢的马

   (1) 如果田忌最慢的马速 > 齐王最慢的马速: 直接比掉 ,赢一局

   (2) 如果田忌最快的马速 <> 齐王最快的马速: 田忌必定输, 为把损失降到最小, 用田忌此时最慢的马与齐王此时最快的马比

   (3) 如果田忌最慢的马速 == 齐王最慢的马速: 

       <1>如果田忌最慢的马 < 齐王最快的马: 必定输,  用田忌此时最慢的马与齐王此时最快的马比

       <2> 速度相等, 说明所有马的速度都相等, 直接结束比赛 

#include<stdio.h>
#include<algorithm>
#include<iostream>
using namespace std;
int cmp(int a, int b)
{
	return a > b;
}
int main()
{
	int n;
	while (scanf("%d", &n))
	{
		if (n == 0) break;
		int a[1005] = { 0 }, b[1005] = { 0 }, i;
		for (i = 0; i < n; i++)
			scanf("%d", &a[i]);
		for (i = 0; i < n; i++)
			scanf("%d", &b[i]);
		sort(a, a + n, cmp);
		sort(b, b + n, cmp);
		int x1 = 0, x2 = 0, y1 = n - 1, y2 = n - 1, sum = 0;
		for (i = 0; i < n; i++)
		{
			if (a[x1] > b[x2])
			{
				sum++; //赢的次数加1
				x1++;
				x2++;
				continue; //比赛继续
			}
			else if (a[x1] < b[x2])
			{
				sum--;
				y1--;
				x2++;
				continue;
			}
			else if (a[x1] == b[x2])
			{
				if (a[y1] > b[y2])
				{
					sum++;
					y1--;
					y2--;
					continue;
				}
				else if (a[y1] < b[y2])
				{
					sum--;
					y1--;
					x2++;
					continue;
				}
				else if (a[y1] == b[y2])
				{
					if (a[y1] < b[x2])
					{
						sum--;
						y1--;
						x2++;
						continue;
					}
					else break;
				}
			}
		}
		printf("%d\n", sum * 200);
	}
	return 0;
}

I - 全排列

给定一个由不同的小写字母组成的字符串,输出这个字符串的所有全排列。 我们假设对于小写字母有 'a' < 'b' < ... < 'y' < 'z',而且给定的字符串中的字母已经按照从小到大的顺序排列。

输入格式

输入只有一行,是一个由不同的小写字母组成的字符串,已知字符串的长度在 11 到 66 之间。

输出格式

输出这个字符串的所有排列方式,每行一个排列。要求字母序比较小的排列在前面。字母序如下定义:

已知 S=s1​s2​...sk​,T=t1​t2​...tk​,则 S < T 等价于,存在 p(1≤p≤k),使得 s1 = t1, s2 = t2, ..., sp−1​=tp−1​,sp​<tp​ 成立。

Sample 1

InputcopyOutputcopy
abc
abc
acb
bac
bca
cab
cba

递归: 每次用完进行标记, 全部用完之后, 递归回调, 重新开始

#include<stdio.h>
#include<string.h>

char a[10], b[10];
int flag[10];
void dfs(int t)
{
	for (int i = 0; i < strlen(a); i++)
	{
		if (flag[i] == 0)
		{
			b[t] = a[i]; //b[t]用来存储数据
			flag[i] = 1;
			dfs(t + 1);
			flag[i] = 0;
		}
	}
	if (t == strlen(a))
		printf("%s\n", b);
}

int main()
{
	scanf("%s", a);
	dfs(0);
	return 0;
}

 J - 区间合并

蒜头君给定 n 个闭区间 [ai​,bi​],其中 i=1,2,...,n。

任意两个相邻或相交的闭区间可以合并为一个闭区间。例如,[1,2] 和 [2,3] 可以合并为 [1,3],[1,3] 和 [2,4] 可以合并为 [1,4],但是 [1,2] 和 [3,4] 不可以合并。

我们的任务是判断这些区间是否可以最终合并为一个闭区间,如果可以,将这个闭区间输出,否则输出 "no"。

输入格式

第一行为一个整数 n,3≤n≤50000。表示输入区间的数量。
之后 n 行,在第 i 行上( n1≤i≤n),为两个整数 ai​ 和 bi​,整数之间用一个空格分隔,表示区间 [ai​,bi​](其中 1≤ai​≤bi​≤10000)。

输出格式

输出一行,如果这些区间最终可以合并为一个闭区间,输出这个闭区间的左右边界,用单个空格隔开;否则输出 "no"。

Sample 1

InputcopyOutputcopy
5
5 6
1 5
10 10
6 9
8 10
1 10

 

先把区间左端点进行排序, 之后判断下一个区间的左端点是否小于等于上一个区间的右端点

#include<stdio.h>
#include<iostream>
#include<algorithm>
using namespace std;
struct hebing
{
	int a, b;

}hb[50005];
int cmp(hebing x, hebing y)
{
	return x.a < y.a || (x.a == y.a && x.b < y.b); //如果左端点相等, 按照右端点升序排序
}
int main()
{
	int n;
	scanf("%d", &n);
	for (int i = 0; i < n; i++)
		scanf("%d %d", &hb[i].a, &hb[i].b);
	sort(hb, hb + n, cmp);
	int max1 = hb[0].b;
	for (int i = 0; i < n-1; i++)
	{
		if (hb[i].b > max1)
			max1 = hb[i].b; //记录最大值
		if (hb[i + 1].a > max1)
		{
			printf("no"); //有一个区间不能合并, 就输出no 退出程序
			return 0;
		}
	}
	if (hb[n - 1].b > max1) //对最后一个区间进行最大值判断
		max1 = hb[n - 1].b;
	printf("%d %d", hb[0].a, max1);
	return 0;
}

 K - 回文数个数

小蒜想知道不超过 n 位的正整数中,有多少个回文数?

输入格式

一个正整数 n, n≤10。

输出格式

一个整数,即回文数个数。

Sample 1

InputcopyOutputcopy
5
1098

注意是正整数, 所以

一位数的回文数是9个, 

 两位数的回文数是11,22,...99 共九个, 

三位数的回文数是101,202,...909, 共十个, 111,212, ...919, 121,222,...929,共9组, 一共9*10

四位数和三位数一样, 中间的两位数需要保持一致

#include<stdio.h>
#include<math.h>
int huiwen(int x)
{
	long long t;
	if (x % 2 == 0)
	{
		 t = 9 * pow(10, (x / 2 - 1));
	}
	else 
	{
		t = 9 * pow(10, ((x+1) / 2 - 1));//奇数和它下一位的偶数回文数相等
	}
	return t;
}
int main()
{
	int n;
	long long t=0;
	scanf("%d", &n);
	for (int i = 1; i <= n; i++)
		t += huiwen(i);
	printf("%lld", t);  
	return 0;
}

O - 补提交卡

蒜头君给自己定了一个宏伟的目标:连续 100 天每天坚持在计蒜客题库提交一个程序。100 天过去了,蒜头君查看自己的提交记录发现有 N 天因为贪玩忘记提交了。于是蒜头君软磨硬泡、强忍着花椰菜鄙视的眼神从花椰菜那里要来 M 张 "补提交卡"。每张 "补提交卡" 都可以补回一天的提交,将原本没有提交程序的一天变成有提交程序的一天。蒜头君想知道通过利用这 M 张补提交卡,可以使自己的 "最长连续提交天数" 最多变成多少天。

输入格式

第一行是一个整数 T(1≤T≤10),代表测试数据的组数。

每个测试数据第一行是 2 个整数 N 和 M (0≤N,M≤100)。

第二行包含 N 个整数 a1​,a2​,...aN​(1≤a1​<a2​<...<aN​≤100),表示第 a1​,a2​,...aN​ 天蒜头君没有提交程序。

输出格式

对于每组数据,输出通过使用补提交卡蒜头君的最长连续提交天数最多变成多少。

Sample 1

InputcopyOutputcopy
3  
5 1  
34 77 82 83 84  
5 2  
10 30 55 56 90  
5 10  
10 30 55 56 90
76  
59
100

先计算提交前m天, 连续天数是多少, 之后再取最大值, 因为输入是没提交的天数, 所以提交m次, 会连成m+1段, 计算最后一段时, 要把最后一天的后一天设置为101

#include<stdio.h>
int main()
{
	int t;
	scanf("%d", &t);
	while (t--)
	{
		int n, m, a[105], flag[105], cnt = 0;
		scanf("%d %d", &n, &m);
		for (int i = 1; i <= n; i++)
			scanf("%d", &a[i]);
		if (m >= n)  //如果补交卡数量多于没提交天数, 直接输出100
			printf("100\n");
		else
		{
			int ans = a[m+1]-1; 
			a[n + 1] = 101;
			for (int i = 1; i <= n - m; i++)
			{
				if (ans < (a[i + m + 1] - a[i] - 1))
					ans = a[i + m + 1] - a[i] - 1;
			}
			printf("%d\n", ans);
		}
	}
	return 0;
}

 Q - 过河

XSEA带领着一组有N个人的队伍,岸边只有一艘船,已知每个人的过河时间为ti,船上一次只能带两个人,每次划船过河的时间等于船上成员的过河时间的最大值,怎么才能让通过的时间最短呢,这可把XSEA给难坏了,想了半天也没有办法你能帮帮他吗?

Input

输入包含多组测试数据。第一行含有一个正整数T,表示数据组数。 每组数据的第一行含有一个整数N。接下来的一行含有N个整数,表示ti。T

Output

对于每组输入数据输出一行,每行包括1个整数,代表该组数据下全员抵达赛场的最少耗时

Sample Input

1
4
1 2 5 10

Sample Output

17

分为四人过河, 比较2*b 与 a+c 的大小

如果2*b >= a+c , 时间为 2*a+c+d 

如果2*b < a+c , 时间为 2*b+a+d 

#include<stdio.h>
#include<iostream>
#include<algorithm>
using namespace std;
int main()
{
	int t;
	scanf("%d", &t);
	while (t--)
	{
		int n, r[10005], sum = 0, a, b, c, d;
		scanf("%d", &n);
		for (int i = 0; i < n; i++)
		{
			scanf("%d", &r[i]);
		}
		sort(r, r + n);
		while (n >= 4)
		{
			a = r[0];
			b = r[1];
			c = r[n - 2];
			d = r[n - 1];
			if (2 * b >= (a + c))
			{
				sum += 2 * a + c + d;
				n -= 2;
			}
			else
			{
				sum += 2 * b + a + d;
				n -= 2;
			}
		}
		if (n == 3)
			sum += r[0] + r[1] + r[2];
		else if (n == 2)
			sum += r[1];
		else if (n == 1)
			sum += r[0];
		printf("%d\n", sum);
	}
	return 0;
}

S - 放苹果

把M个同样的苹果放在N个同样的盘子里,允许有的盘子空着不放,问共有多少种不同的分法?(用K表示)5,1,1和1,5,1 是同一种分法。

Input

第一行是测试数据的数目t(0 <= t <= 20)。以下每行均包含二个整数M和N,以空格分开。1<=M,N<=10。

Output

对输入的每组数据M和N,用一行输出相应的K。

Sample

InputcopyOutputcopy
1
7 3
8

如果盘子个数(n)<=1, 只有一种情况

如果盘个数(n) > 苹果个数(m), 一定装不满所有盘子, 最多只能装满m个盘子

如果盘个数(n) < 苹果个数(m), 分为有空盘子和没空盘子两种情况 

#include<stdio.h>
int apple(int m, int n)
{
	if (n <= 1) return 1;
	if (n > m) return apple(m, m);
	else return apple(m, n - 1) + apple(m - n, n);
}
int main()
{
	int t, m, n, k;
	scanf("%d", &t);
	while (t--)
	{
		scanf("%d %d", &m, &n);
		k = apple(m, n);
		printf("%d\n", k);

	}
	return 0;
}

 T - 数列极差

题目描述

佳佳的老师在黑板上写了一个由 n 个正整数组成的数列,要求佳佳进行如下操作:每次擦去其中的两个数 a 和 b,然后在数列中加入一个数 a×b+1,如此下去直至黑板上剩下一个数为止,在所有按这种操作方式最后得到的数中,最大的为 max,最小的为 min, 则该数列的极差定义为 M=max−min。

由于佳佳忙于准备期末考试,现请你帮助他,对于给定的数列,计算出相应的极差 M。

输入格式

第一行为一个正整数 n 表示正整数序列的长度;
在接下来的 n 行中,每行输入一个正整数。
接下来的一行有一个 0,表示数据结束。

输出格式

输出只有一行,为相应的极差 d。

样例

InputcopyOutputcopy
3
1
2
3
0
2

 计算最大值, 需要每次都要划掉最小的两个数

计算最小值,需要每次划掉最大的两个数, 因为每次插入的数一定比原来的数大, 所以不需要重新排序

#include<stdio.h>
#include<iostream>
#include<algorithm>
using namespace std;
int n, i, j, a[50005], b[50005];
int cmp(int a,int b)
{
	return a>b;
}
int main()
{
	int x, max, min;
	scanf("%d", &n);
	for (i = 0; i < n; i++)
	{
		scanf("%d", &a[i]);
		b[i] = a[i]; //b[i]复制a[i]的值
	}
	scanf("%d", &x);
	sort(a , a + n);
	for (i = 1; i < n; i++)
	{
		a[i] = a[i - 1] * a[i] + 1;
		sort(a + i, a + n); //每次插入一个数,进行排序, 因为不确定插入的数与原来数的大小
	}
	max = a[n-1];

	sort(b , b + n, cmp);
	for (i = 1; i < n; i++)
	{
		b[i] = b[i - 1] * b[i] + 1;
	}
	min = b[n-1];
	printf("%d", max - min);
	return 0;
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值