蓝桥杯算法提高VIP-排列式

题目

题目链接

题解

全排列。


这种题一般就是全排列,9! < 4e5
这里有点小技巧,就是结果必然是个四位数,第一个乘数要么是一位数要么是两位数。

为什么这么说呢?
我们知道假设第一个乘数a位,第二个乘数b``位,那么他们乘积的位数要么是a+b位,要么是a+b-1
如果结果是个三位数,那么还剩六位数,无论将这六位数怎么分配给两个乘数都无法满足乘积为三位,同理结果为一位和两位也都不可能;
如果结果是个五位数,那么还剩四位,四位数分配给两个乘数最多乘出来个四位数,因此还是不行,同理大于五位更不行;


很显然只有结果为四位数可行。当结果为四位数时,乘数可能是多少位呢?
题目要求乘数互换属于一个式子,同时要求乘数小的先输出,因此我们只需考虑第一个乘数的位数,无非是一位或两位嘛。当第一个乘数为一位时,第二个乘数为四位;当第一个乘数为两位时,第二个乘数为三位;如果也输出第一个乘数为三位的情况的话,那么第二个乘数就是两位了,这必然会出现重复输出。因此,我们只用输出第一个乘数是一位和两位的情况就行了。


如何保证使用next_permutation就能按要求的大小输出?
首先我们要明白next_permutation的实现原理,正如其名,这个函数就是让一个元素递增排序的数组不断变大,每次后出现的都会大于先出现的。据说它也是通过递归实现的,因此不允许排序的个数太多。如果还是不能理解可以完整的输出一个序列的全部全排列模拟一下。
对于每一种全排列,就对应着一种乘积,我们先输出第一个是取一位的情况,再输出第一个乘数为两位的情况就行了。

代码

#include<bits/stdc++.h>
using namespace std;
const int N = 1e3;

int a[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
int num1, num2, num3;

int main()
{
	do { 
		// xxxx = x * xxxx
		num1 = num2 = num3 = 0;
		for(int i = 0;i < 4;i ++) num1 = num1*10 + a[i];
		for(int i = 4;i < 5;i ++) num2 = num2*10 + a[i];
		for(int i = 5;i < 9;i ++) num3 = num3*10 + a[i];
		if(num1 == num2*num3) 
		printf("%d = %d x %d\n", num1, num2, num3);
		
		// xxxx = xx * xxx
		num1 = num2 = num3 = 0;
		for(int i = 0;i < 4;i ++) num1 = num1*10 + a[i];
		for(int i = 4;i < 6;i ++) num2 = num2*10 + a[i];
		for(int i = 6;i < 9;i ++) num3 = num3*10 + a[i];
		if(num1 == num2*num3) 
		printf("%d = %d x %d\n", num1, num2, num3);
		
	} while(next_permutation(a, a+9));

	return 0;
}
/*
4396 = 28 x 157
5346 = 18 x 297
5346 = 27 x 198
5796 = 12 x 483
5796 = 42 x 138
6952 = 4 x 1738
7254 = 39 x 186
7632 = 48 x 159
7852 = 4 x 1963
*/
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不牌不改

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值