凑平方数

24 篇文章 1 订阅
21 篇文章 0 订阅

把0~9这10个数字,分成多个组,每个组恰好是一个平方数,这是能够办到的。
比如:0, 36, 5948721

再比如:
1098524736
1, 25, 6390784
0, 4, 289, 15376
等等...

注意,0可以作为独立的数字,但不能作为多位数字的开始。
分组时,必须用完所有的数字,不能重复,不能遗漏。

如果不计较小组内数据的先后顺序,请问有多少种不同的分组方案?

注意:需要提交的是一个整数,不要填写多余内容。


这道题目并不难想,获得这10个数的全排列,然后将这10个数进行划分,最后去重即可

思路:

1.先打表,用于判断一个数是不是平方数,至于为什么不用sqrt( )这个函数,主要是这个函数返回值是double类型,数字类型转换的时候怕出现精度丢失引起的错误

2.用algorithm下的next_permutation( )函数生成全排列

3.深搜,对这个序列进行划分,注意一点,划分后的各组数字是不能以0为起始数字(除非是单个0),可以通过判断数字位数来解决

4.去重,将划分好的数字序列排序之后生成字符串(stringstream的作用,感兴趣的同学可以看一下),map判断是否出现过,我选择将一个序列的数字之间加上空格之后的得到字符串作为去重标准(为什么要这么做?举个例子 0,1,2345,6789(假设这是一个合法的序列)0,1,234,567,89(假设这是也一个合法的序列),那么同一个序列可能有多种划分方法,加上空格作为间隔,就可以将它们区分,如果结果是294,295之类的可以这么试试)

5.这个程序在我的电脑上运行的挺慢的(毕竟复杂度在那里)

300
--------------------------------
Process exited after 48.16 seconds with return value 0
请按任意键继续. . .

#include<iostream>
#include<sstream> 
#include<algorithm>
#include<string>
#include<cmath>
#include<map>
using namespace std;
int an[10]={0,1,2,3,4,5,6,7,8,9},cnt=0;
long long bn[10];
map<long long,int> lli;
map<string,int> si;
void dfs(int pos,int len,int next)
{
	if(len==10)
	{
		string str="";
		long long cn[10]={0};
		for(int i=0;i<next;i++)
			cn[i]=bn[i];
		sort(cn,cn+next);
		for(int i=0;i<next;i++)
		{
			stringstream stream;
			string tmp;
			stream << cn[i];
			stream >> tmp;
			str+=tmp;
			str+=" ";
		}
		if(si[str]==0)
		{
			si[str]=1;
			//cout << str << endl;
			cnt++;
		}
		return ;
	}
	long long t=0;
	for(int i=len;i<10;i++)
	{
		t=t*10+an[i];
		if(t==0)
		{
			bn[next]=t;
			dfs(i+1,len+i-pos+1,next+1);
		}
		else if(lli[t]==1&&(int)log10(t)==i-pos)
		{
			bn[next]=t;
			dfs(i+1,len+i-pos+1,next+1);
		}		
	}
}
int main()
{
	for(long long i=0;i<100000;i++)
		lli[i*i]=1;
	do
	{
		dfs(0,0,0); 
	}while(next_permutation(an,an+10));
	cout << cnt;
	return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值