蓝桥杯 带分数

15 篇文章 0 订阅
9 篇文章 0 订阅

思路:

刚开始暴力枚举,33分,优化一下,66分。

再优化,还是有组数据TLE。网上有份 java 代码,改成 C++ 后终于100了!

还是方法有问题,以小见大,不同的方法做事,会有不同的结果。当一种办法行不通时,改变一下思路,或许就有了答案。

dfs + 剪枝:

首先,暴力 1 - 9 的全排列,假设其中一个为 246517983,n = 100

我们令 N = n1 + n2 / n3,则 n1 的截取终点 Rn1 取值:1 - lenN (N 的长度)

然后,若 n1 取24,则 n2 的截取终点 Rn2 取值:Rn1 + ( 10 - Rn1 ) / 2 - 8

最后,判断是否符合条件就OK了!

代码:

#include <stdio.h>
#include <iostream>
#include <cstring>
using namespace std ;

int a[ 15 ] , vis[ 15 ] , cnt , lenN ;
int sum( int Left , int Right )		//将 a[Left - Right] 转换为整数  
{
	int s = 0 ;
	for( int i = Left ; i <= Right ; i++ ) s = 10 * s + a[ i ] ;
	return s ;
}
void dfs( int L , int sn , int N )
{
	int n1, n2 , n3 , Rn1 , Rn2 ;
	if( L == sn ) {					//若已经生成一个全排列  
		for( Rn1 = 1 ; Rn1 <= lenN ; Rn1++ ) {
			n1 = sum( 1 , Rn1 ) ;		//n1 取 a[1 - Rn1] 
			if( n1 >= N ) return ;		//不符合,剪枝 
			for( Rn2 = Rn1 + ( 10 - Rn1 ) / 2 ; Rn2 < 9 ; Rn2++ ) {
				n2 = sum( Rn1 + 1 , Rn2 ) ;
				n3 = sum( Rn2 + 1 , 9 ) ;
				if( n2 >= n3 && n2 % n3 == 0 && N == n1 + n2 / n3 ) cnt++ ;
			}
		}
	}
	else {
		for( int i = 1 ; i <= 9 ; i++ ) {    //全排列,下面与小白书127页素数环类似 
			if( vis[ i ] ) continue ;		//若 i 已经用过,结束本次循环,判断下一个  
			a[ L ] = i ;				//i 没用过,将当前数字设置为 i  
			vis[ i ] = 1 ;				//标记  
			dfs( L + 1 , sn , N ) ;		//设置下一个数字  
			vis[ i ] = 0 ;				//清除标记  
		}
	}
}
int main()
{
	int N ;
	scanf( "%d" , &N ) ;
	int tN = N ;
	while( tN ) {
	    lenN++ ;		// lenN 为 N 的长度  
	    tN /= 10 ;
	}
	dfs( 1 , 10 , N ) ;
	cout << cnt << endl ;
	return 0 ;
} 

这里我们还可以用C++里的STL生成全排列,就是一个循环,一个函数,so easy!

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

int a[ 15 ] , vis[ 15 ] , cnt , lenN ;
int sum( int Left , int Right )		//将 a[Left - Right] 转换为整数
{
	int s = 0 ;
	for( int i = Left ; i <= Right ; i++ ) s = 10 * s + a[ i ] ;
	return s ;
}
int main()
{
	int N ;
	int n1, n2 , n3 , Rn1 , Rn2 ;
	scanf( "%d" , &N ) ;
	int tN = N ;
	while( tN )
	{
	    lenN++ ;		// lenN 为 N 的长度
	    tN /= 10 ;
	}
	for (int i = 1; i <= 9; i++) a[i] = i;
	do
	{
		for( Rn1 = 1 ; Rn1 <= lenN ; Rn1++ ) {
			n1 = sum( 1 , Rn1 ) ;		//n1 取 a[1 - Rn1]
			if( n1 >= N ) continue ;		//不符合,继续下一个排列
			for( Rn2 = Rn1 + ( 10 - Rn1 ) / 2 ; Rn2 < 9 ; Rn2++ ) {
				n2 = sum( Rn1 + 1 , Rn2 ) ;
				n3 = sum( Rn2 + 1 , 9 ) ;
				if( n2 >= n3 && n2 % n3 == 0 && N == n1 + n2 / n3 ) cnt++ ;
			}
		}
	} while (next_permutation(a + 1, a + 9 + 1));


	cout << cnt << endl ;
	return 0 ;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值