【PAT乙】1005/1023/1020/1030

22 篇文章 0 订阅
/*
*时间:2018年4月9日08:43:45-2018年4月9日09:08:57
*题号:1005. 继续(3n+1)猜想
*语言:C++ (g++ 4.7.2)
*分数:25
*题目描述:

卡拉兹(Callatz)猜想已经在1001中给出了描述。在这个题目里,情况稍微有些复杂。

当我们验证卡拉兹猜想的时候,为了避免重复计算,可以记录下递推过程中遇到的每一
个数。例如对n=3进行验证的时候,我们需要计算3、5、8、4、2、1,则当我们对n=5、8、4、2
进行验证的时候,就可以直接判定卡拉兹猜想的真伪,而不需要重复计算,因为这4个数已经在
验证3的时候遇到过了,我们称5、8、4、2是被3“覆盖”的数。我们称一个数列中的某个数n为“关键数”,
如果n不能被数列中的其他数字所覆盖。

现在给定一系列待验证的数字,我们只需要验证其中的几个关键数,就可以不必再重复验证余下的数字。
你的任务就是找出这些关键数字,并按从大到小的顺序输出它们。

输入格式:每个测试输入包含1个测试用例,第1行给出一个正整数K(<100),第2行给出K个互不相同的待
验证的正整数n(1<n<=100)的值,数字间用空格隔开。

输出格式:每个测试用例的输出占一行,按从大到小的顺序输出关键数字。数字间用1个空格隔开,
但一行中最后一个数字后没有空格。
输入样例:

6
3 5 6 7 8 11

输出样例:

7 6
*/
//还是散列的思想吧,把每个数进行3n+1过程中的HashTable建立出来,
//然后从大到小排序一下HashTable上没有覆盖到的输入的这些值
#include <iostream>
using namespace std;
#include <vector>
#include <algorithm>
#define Debug false
int main()
{
	vector <int> v;
	int N;
	cin>>N;
	int num[N];
	bool HashTable[10000] = {false};//由于迭代之后可能会比100大,所以数组大小不能只设置为100,
	for (int i=0; i<N; i++)         //原来设的1000段错误了,1000还不够用,多设一些吧
	{
		cin>>num[i];
		int temp = num[i];//这个很关键,不能直接用num[i]去做判断和除法,这样会改变原来的num[i]的值
		while (temp != 1)
		{
			if (temp % 2 == 0)
			{
				temp /= 2;
			}
			else 
				temp = (3*temp+1)/2;
			if (Debug) cout<<temp<<" ";
			HashTable[temp] = true;//对每个输入值进行3n+1假设,然后在同一个HashTable上记录
		}
	}
	for (int i=0; i<N; i++)
	{	if (Debug) cout<<HashTable[num[i]]<<" ";
		if (!HashTable[num[i]])
			v.push_back(num[i]);	
	}
	if (Debug) cout<<v.size();
	sort(v.rbegin(), v.rend());//从大到小排列只需要用反向迭代器就可以了,不需要再自己写cmp函数
	if (Debug) for(int i=0; i<v.size(); i++)
		cout<<v[i];
	for (int i=0; i<v.size(); i++)
	{
		if (i != v.size()-1) cout<<v[i]<<" ";//最后一个不输出空格
		else cout<<v[i];
	}
		
	return 0;
}


/*
*时间:2018年4月9日09:35:50-2018年4月9日09:44:47
*题号:1023. 组个最小数
*语言:C++ (g++ 4.7.2)
*分数:20
*题目描述:

给定数字0-9各若干个。你可以以任意顺序排列这些数字,但必须全部使用。
目标是使得最后得到的数尽可能小(注意0不能做首位)。例如:给定两个0,两个1,三个5,一个8,
我们得到的最小的数就是10015558。

现给定数字,请编写程序输出能够组成的最小的数。

输入格式:

每个输入包含1个测试用例。每个测试用例在一行中给出10个非负整数,顺序表示我们拥有
数字0、数字1、……数字9的个数。整数间用一个空格分隔。10个数字的总个数不超过50,
且至少拥有1个非0的数字。

输出格式:

在一行中输出能够组成的最小的数。
输入样例:

2 2 0 0 0 3 0 0 1 0

输出样例:

10015558

*/
//思路:看到这题就忍不住刷了,思路和之前PATest类似
#include <iostream>
using namespace std;

int main()
{
	int num[10];
	for (int i=0; i<10; i++)
		cin>>num[i];
	for (int i=1; i<10; i++)
	{
		if (num[i] != 0)
		{
			cout<<i;
			num[i]--;
			break;
		}
	}
	for (int i=0; i<50; i++)   //个数总和不超过50个,那种有输出那种,从前面到后面
	{
		if (num[0] != 0 ) {cout<<"0"; num[0]--;}
		else if (num[1] != 0 ) {cout<<"1"; num[1]--;}
		else if (num[2] != 0 ) {cout<<"2"; num[2]--;}
		else if (num[3] != 0 ) {cout<<"3"; num[3]--;}
		else if (num[4] != 0 ) {cout<<"4"; num[4]--;}
		else if (num[5] != 0 ) {cout<<"5"; num[5]--;}
		else if (num[6] != 0 ) {cout<<"6"; num[6]--;}
		else if (num[7] != 0 ) {cout<<"7"; num[7]--;}
		else if (num[8] != 0 ) {cout<<"8"; num[8]--;}
		else if (num[9] != 0 ) {cout<<"9"; num[9]--;}
		else break;	
	}
	
	return 0;
}


/*
*时间:2018年4月9日12:08:27-2018年4月9日12:40:02
*题号:1020. 月饼
*语言:C++ (g++ 4.7.2)
*分数:25
*题目描述:

月饼是中国人在中秋佳节时吃的一种传统食品,不同地区有许多不同风味的月饼。现给定所有种类月饼的库
存量、总售价、以及市场的最大需求量,请你计算可以获得的最大收益是多少。

注意:销售时允许取出一部分库存。样例给出的情形是这样的:假如我们有3种月饼,其库存量分别为
18、15、10万吨,总售价分别为75、72、45亿元。如果市场的最大需求量只有20万吨,那么我们最大收益
策略应该是卖出全部15万吨第2种月饼、以及5万吨第3种月饼,获得 72 + 45/2 = 94.5(亿元)。

输入格式:

每个输入包含1个测试用例。每个测试用例先给出一个不超过1000的正整数N表示月饼的种类数、以及不超过
500(以万吨为单位)的正整数D表示市场最大需求量。随后一行给出N个正数表示每种月饼的库存量(以万吨
为单位);最后一行给出N个正数表示每种月饼的总售价(以亿元为单位)。数字间以空格分隔。

输出格式:

对每组测试用例,在一行中输出最大收益,以亿元为单位并精确到小数点后2位。
输入样例:

3 20
18 15 10
75 72 45

输出样例:

94.50
*/
//思路:把单价从高到底排列,写卖高的,卖完了再卖次高的以此类推,每次拿出这种商品的所有库存
//如果发现供给大于需求了,就把这种商品减掉,再看看差多少补多少,然后按单价算钱
#include <iostream>
using namespace std;
#include <vector>
#include <algorithm>
#include <stdio.h>
struct yuebing
{
	double kucun;//第一次库存设的是int类型的结果一个点没有编译过去,改成double就都过了
	double shoujia;//目前还没发现问题出在哪儿,但是在不影响运算时间的情况下尽量用double吧
	double danjia;
	
};
bool cmp(yuebing a, yuebing b)
{
	return (a.danjia > b.danjia);
}

int main()
{
	int N, need;
	cin>>N>>need;
	yuebing YB[N];
	vector <yuebing> v;
	for (int i=0; i<N; i++)
	{
		cin>>YB[i].kucun;
	}
	for (int i=0; i<N; i++)
	{
		cin>>YB[i].shoujia;
		YB[i].danjia = YB[i].shoujia / YB[i].kucun;
		v.push_back(YB[i]);
	}
	sort (v.begin(), v.end(), cmp);//单价从高到低排列
	int gongji = 0;
	double yingli = 0;
	for (int i=0; i<N; i++)
	{	
		gongji += v[i].kucun; //先加上这样月饼的库存和售价
		yingli += v[i].shoujia;
		if (gongji > need) //发现供给大于库存了再减回去处理,先斩后奏的处理方法
		{
			yingli = yingli - v[i].shoujia;
			gongji = gongji - v[i].kucun;
			yingli +=  (need - gongji)*v[i].danjia;//按单价*重量来计算实际收益
			break;
		}
	}
	printf("%.2f",yingli);
	
	return 0;
}

/*
*为了比较数据除法的结果做了以下小实验,结果在除法中有一部分为double结果就为double类型
*/
#include <iostream>
using namespace std;
#include <stdio.h>

int main()
{
	int a = 1;
	double b = 1;
	double c = 3;
	int d = 3;
	printf("int / double %.3f\n",a/c);
	printf("double / double %.3f\n",b/c);
	printf("double / int %.3f\n",b/d);
	printf("int / int %.3f\n",a/d);
	
	double e = a / c;
	double f = b / d;
	double g = b / c;
	double h = (double) a/d;//括号必须加!
	cout<<"int / double "<<e<<endl;
	cout<<"double / int "<<f<<endl;
	cout<<"double / double "<<g<<endl;
	cout<<"(double) a/d"<<h<<endl;
	cout<<"(double) a/d"<<(double) a/d<<endl;
	return 0;
}
/*
int / double 0.333
double / double 0.333
double / int 0.333
int / int 0.333
int / double 0.333333
double / int 0.333333
double / double 0.333333
(double) a/d0.333333
(double) a/d0.333333
*/

#include <iostream>  
using namespace std;  
#include <stdlib.h>

int main(int argc,char *argv[])  
{  
    char a[] = "2.5645";
    float A = atof(a);
	char b[] = "3.855";
    float B = atof(b);
	double C = A+B;
    cout<<A<<" "<<B<<" "<<C<<endl;  
     
    return 0;     
      
}  
/*
2.5645 3.855 6.4195
测试了一下字符串转成双精度的函数 atof atoi是转成int
另外spintf可以输出字符串,c++直接用cout就可以看
数字转换成字符串的还没测试
*/



/*
*时间:2018年4月9日18:41:55-2018年4月9日19:36:27
*题号:1030. 完美数列
*语言:C++ (g++ 4.7.2)
*分数:25
*题目描述:
给定一个正整数数列,和正整数p,设这个数列中的最大值是M,最小值是m,如果M <= m * p,
则称这个数列是完美数列。

现在给定参数p和一些正整数,请你从中选择尽可能多的数构成一个完美数列。

输入格式:

输入第一行给出两个正整数N和p,其中N(<= 10^5)是输入的正整数的个数,p(<= 10^9)是给定的参数。
第二行给出N个正整数,每个数不超过10^9。

输出格式:

在一行中输出最多可以选择多少个数可以用它们组成一个完美数列。
输入样例:

10 8
2 3 20 4 5 1 6 7 8 9

输出样例:

8
*/
//思路:这题自己写的时候先是写了个二重循环倒序来找最大的符合条件的数,因为有可能有好多数是相等的
//但是这样出现了运行超时,果然这样的双重循环代价太大了
//于是看了下二分法查找的原理,然后学习了下 upper_bound函数才解决,而且代码也节省了不少,头问价应该是algorithm吧
#include <iostream>
using namespace std;
#include <algorithm>
#define Debug false
int main()
{	
	long long N, p;
	cin>>N>>p;
	long long num[N];//注意p和输入的值是10^9,特别是两者相乘,一定要用最长的long long
	for (long i=0; i<N; i++)
	{
		cin>>num[i];
	}
	sort (num, num+N); //默认是从小到大排列的,这里需要的就是从小到大排列,画蛇添足了
	long maxLenth = 0;
	for (long i=0; i<N; i++)
	{
		//返回num[i+1]到num[N]中第一个大于num[i]*p的数的位置,再减去初始值即为相对位置
		//也要注意了这里是大于,和本题意,但是如果把本题改成<num[i]*p的话就是要找到等于num[i]*p也是可以的
		//就不能直接用这个函数了,要做一些改动
		int temp = upper_bound(num+i+1, num+N, (long long)num[i] * p) - num;//类型转换是类型加括号
		maxLenth = max (maxLenth, temp - i);//max函数了解一下,免得自己写三目或者是if了
	}
	cout<<maxLenth;
	
	return 0;
}

//这是原来自己写的查找,差的一逼
#include <iostream>
using namespace std;
#include <algorithm>
int main()
{	
	long int N, p;
	cin>>N>>p;
	long int num[N];
	for (int i=0; i<N; i++)
	{
		cin>>num[i];
	}
	sort (num, num+n);
	int maxLenth = 0;
	for (int i=0; i<N; i++)
	{
		int temp = num[i] * p;
		for (int j=N-1; j>=0; j++)
		{	
			if (temp >= num[N-1])
			{
				if (maxLenth < N-1-i)
					maxLenth = N-i;
			}
			else if (temp >= num[j] && temp < num[j+1])
			{
				if (maxLenth < j+1-i)
					maxLenth = j+1-i;
			}					
		}
	}
	cout<<maxLenth;
	
	return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值