蓝桥杯试题 历届试题 带分数(C++版)

问题描述
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 使用了STL(为蓝桥杯历届真题解析课程的解法):

但我觉得这博客写的更好:
蓝桥杯 历年真题 带分数(全排列切割)–作者DeathYmz

#include <iostream>
#include<string>
#include<algorithm>
#include <stdio.h>
using namespace std;
int parse(const char* arr, int pos, int len) {
	int ans = 0;
	int t = 1;
	for (int i = pos + len - 1; i >= pos; i--)
	{
		ans += (arr[i] - '0') * t;
		t *= 10;
	}
	return ans;
}

int main() {
	int N;
	cin >> N;
	int ans = 0;
	string s = "123456789";
	do
	{
		const char* str = s.c_str();
		for (int i = 0; i <= 7; i++)//i <= 7,因为intb,intc至少要一位
		{
			//string a = s.substr(0, i);
			//获取字符串s在o~i的子串
			//反复截取字符串,需要消耗很大的内存
			//int inta = atoi(a.c_str());
			//atoi是#include <stdlib.h>中的,意思为字符串转整形
			int inta = parse(str, 0, i);
			//完成了上面注释的两个代码,同时对内存消耗减少了
			if (inta >= N)break;
			for (int j = 1; j <= 9 - 1 - i; j++)
				//int j = 1,因为intb至少要一位
	//j <= 9 - 1 - i,因为总共9位,inta为i位,intc至少一位(当然,写成 j <= 9,这里的是做了些优化)
			{
				//string b = s.substr(i, j);
				//s.substr(i,j)表示从下标为i的位置开始截取j位
				//string c = s.substr(i + j);
				//s.substr(i + j)表示从下标i + j开始一直到字符串结束
				//int intb = atoi(b.c_str());
				//int intc = atoi(c.c_str());

				int intb = parse(str, i, j);
				int intc = parse(str, i + j, 9 - i - j);
				if (intb % intc == 0 && inta + intb / intc == N)
				{
					/*cout << inta << " " << intb << " " << intc << " " << endl;*/
					ans++;
				}
			}
		}
	} while (next_permutation(s.begin(), s.end()));
	//next_permutation(s.begin(), s.end())是STL中的全排列
	cout << ans;
	return 0;
}

代码2(自己通过dfs写全排列的部分):

#include<iostream>
#include<string.h>
using namespace std;
int visit[10] = { 0 };//作为是否已被取的标志
int s[10];
int ans = 0;
int N;
void found(int s[])//目的,得到满足条件的x,y,z
{
	int x, y, z;
	for (int i = 1; i < 9; i++)//对于要对三个变量,在一个范围内,可参考下面的方式
	{
		for (int j = i + 1; j < 9; j++)
		{
			x = y = z = 0;
			for (int k = 0; k < 9; k++)
			{
				if (k < i)x = x * 10 + s[k + 1];
				else if (k < j)y = y * 10 + s[k + 1];
				else z = z * 10 + s[k + 1];
			}
			if (y % z == 0 && x + y / z == N)
			{
				/*cout << x << " " << y << " " << z << " " << endl;*/
				ans++;
			}
		}
	}
}

void dfs(int pos, int n)//通过dfs(深度搜索),得到1~9的全排列
{
	if (pos == n)
		found(s);
	else
	{
		for (int i = 1; i <= 9; i++)
		{
			if (!visit[i])
			{
				s[pos] = i;
				visit[i] = 1;
				dfs(pos + 1, n);
				visit[i] = 0;
			}
		}
	}
}
int main()
{
	cin >> N;
	dfs(1, 10);
	cout << ans << endl;
	return 0;
}

欢迎任何形式的转载,但请务必注明出处。

限于本人水平,如果文章和代码有表述不当之处,还请不吝赐教。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值