蓝桥杯 历届试题 PREV-3 带分数 搜索

历届试题 带分数
时间限制:1.0s 内存限制:256.0MB
问题描述
100 可以表示为带分数的形式:100 = 3 + 69258 / 714。
还可以表示为:100 = 82 + 3546 / 197。
注意特征:带分数中,数字1~9分别出现且只出现一次(不包含0)。
类似这样的带分数,100 有 11 种表示法。
输入格式
从标准输入读入一个正整数N (N<1000*1000)
输出格式
程序输出该数字用数码1~9不重复不遗漏地组成带分数表示的全部种数。
注意:不要求输出每个表示,只统计有多少表示法!
样例输入1
100
样例输出1
11
样例输入2
105
样例输出2
6

分析:
  首先,这道题要求数字1~9分别出现且只出现一次(不包含0),就说明肯定是一道全排列的题,这里我推荐一个库函数next_permutation(全排列算法),具体可参考https://blog.csdn.net/c18219227162/article/details/50301513
  其次,我们再分析搜索条件。题中例题是 100 = 3 + 69258 / 714 100 = 3 + 69258 / 714 100=3+69258/714,可以大致看为 n = a + b / c n = a + b / c n=a+b/c的格式。
  那么,全排列次数太多,1-9的全排列足足有362880种,可能最后的答案也就十几种,所以我们就需要一个好的剪枝条件了。
  
剪枝条件:
  1. 由题意: n = a + b / c n = a + b / c n=a+b/c
  2. 根据1式,a一定小于n: a &lt; n a &lt; n a<n
  3. 由于a一定是整数,所以b/c的结果也是整数: b % c = = 0 b \% c == 0 b%c==0
  
a,b,c的取值范围:
  1. 既然a,b,c由1-9组成,每一个数有且只有一个,我们不妨将1-9的全排列拆分成三段,即前面lena个数组合为a,中间lenb个数组合为b,剩余的数为a。
    例:n = 100, 1-9排列为369258714时,第一个数为a, 中间5个数为b,剩余3个数为c,即100 = 3 + 69258 / 714;
  2. 根据前面的剪枝条件中说过的 a &lt; n a&lt;n a<n,我们就可以在每次的全排列前面开始,按位依次取a的值,直到不满足条件为止。
    例:n = 100,在369258714这种情况下,第一次循环a=3,接下来去判断b和c,继而判断是否满足要求再lena++;第二次循环a=36……lena++;第三次循环a=369,不满足条件,跳出循环,进入下一次排列。
  3. b和c的取值也有技巧,前面说过 b % c = = 0 b\%c==0 b%c==0,而b和c都是1-9组成的正整数,要满足被除条件,b一定是大于等于c的,所以b的长度一定大于等于c的长度。
    例:n = 100,在369258714排列,a = 3的情况下:b的取值可直接从6925开始,这时c=8714,不满足条件;第二次循环b=69258,c=714,经 b % c = = 0 , n = = a + b / c b\%c == 0, n == a + b / c b%c==0,n==a+b/c两个剪枝条件的判断下,恰好符合条件,res++;第三次循环b=692587,c=14……这样去按位循环判断,直接从剩余长度的一半开始。
 
问题都解决了,最后代码如下:

/*
123456789全排列,有362880种可能 
1. n=a+b/c
2. a<n;
3. b%c=0
*/

#include <iostream>
#include <algorithm>
using namespace std;

int ans[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};

//将数组begin到end的数合并为一个数 
int doNum(int *begin, int *end)
{
	int res = 0, *p;
	for(p = begin; p != end; p++)
		res = res * 10 + *p;
	return res;
}

int main()
{
	int n;
	int res = 0;	//符合条件的个数 
	int a, b, c;
	int lena, lenb;	//a和b的长度 
	
	cin >> n;
	
	do	//1-9全排列,一共有362880种可能
	{
		//将1-9全排列,拆成三段分别为a,b,c然后判断是否符合条件 
		//1. 取a,条件2:a < n
		for(lena = 1, a = doNum(ans, ans + lena); a < n; a = doNum(ans, ans + ++lena))	//按长度取
		{
			//2. 取b和c,b的长度至少是剩余长度的一半以上
			for(int piv = (9 + lena) / 2; piv < 9; piv++)
			{
				b = doNum(ans + lena, ans + piv);
				c = doNum(ans + piv, ans + 9);
				if(b % c == 0 && n == a + b / c)	//条件1,3:b & c = 0, n = a + b / c
				{
					res++;
					//cout << n << " = " << a << " + " << b << " / " << c << endl;
				}
			}
		}
	}while(next_permutation(ans, ans + 9));	//依次遍历下一种排列组合,如果没有下一个排列组合,便返回false,否则返回true
	
	cout << res << endl;
	
	return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
水资源是人类社会的宝贵财富,在生活、工农业生产中是不可缺少的。随着世界人口的增长及工农业生产的发展,需水量也在日益增长,水已经变得比以往任何时候都要珍贵。但是,由于人类的生产和生活,导致水体的污染,水质恶化,使有限的水资源更加紧张。长期以来,油类物质(石油类物质和动植物油)一直是水和土壤中的重要污染源。它不仅对人的身体健康带来极大危害,而且使水质恶化,严重破坏水体生态平衡。因此各国都加强了油类物质对水体和土壤的污染的治理。对于水中油含量的检测,我国处于落后阶段,与国际先进水平存在差距,所以难以满足当今技术水平的要求。为了取得具有代表性的正确数据,使分析数据具有与现代测试技术水平相应的准确性和先进性,不断提高分析成果的可比性和应用效果,检测的方法和仪器是非常重要的。只有保证了这两方面才能保证快速和准确地测量出水中油类污染物含量,以达到保护和治理水污染的目的。开展水中油污染检测方法、技术和检测设备的研究,是提高水污染检测的一条重要措施。通过本课题的研究,探索出一套适合我国国情的水质污染现场检测技术和检测设备,具有广泛的应用前景和科学研究价值。 本课题针对我国水体的油污染,探索一套检测油污染的可行方案和方法,利用非分散红外光度法技术,开发研制具有自主知识产权的适合国情的适于野外便携式的测油仪。利用此仪器,可以检测出被测水样中亚甲基、甲基物质和动植物油脂的污染物含量,为我国众多的环境检测站点监测水体的油污染状况提供依据。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值