洛谷 P8615 [蓝桥杯 2014 国 C] 拼接平方数

题面

题目描述

小明发现 $49$ 很有趣,首先,它是个平方数。它可以拆分为 $4$$9$,拆分出来的部分也是平方数。$169$ 也有这个性质,我们权且称它们为:拼接平方数。

$100$ 可拆分 $1,00$,这有点勉强,我们规定,$0,00,000$ 等都不算平方数。

小明想:还有哪些数字是这样的呢?

你的任务出现了:找到某个区间的所有拼接平方数。

输入格式

两个正整数 $a,b(a<b<10^6)$

输出格式

若干行,每行一个正整数。表示所有的区间 $[a,b]$ 中的拼接平方数,从小到大输出。

样例 #1

样例输入 #1

169 10000

样例输出 #1

169
361
1225
1444
1681
3249
4225
4900
9025

提示

时限 1 秒, 256M。蓝桥杯 2014 年第五届国赛

解题

题目大意

给定一个区间,求区间中所有拼接平方数。

思路

先判断该区间某数是否是平方数,再将该数拆成两部分,分别判断其是否是平方数,如果是就输出。要注意 $sqrt()$ 所表示的数不是整型,所以要强制转型 $int(sqrt())$ 才能判断(我在这卡了半天)。

根据题目意义,我们可以写出一个判断这个数是否为平方数的$O(log(n))$的函数:

bool pd(int n)
{
	int i;
	for(i=1;i<=sqrt(n);i++)
    {//为了节省时间,到n的平方根就好了
		if(i*i==n)
        {//如果有一个整数的平方等于n
			return true;
			break;
		}
	}
    return false;
}

但是为了节省时间,我们可以直接用  $O(1)$ 的C++自带的函数 $sqrt()$ 来判断:

int(sqrt(x))*int(sqrt(x))==x

这样我们就可以得出一段较为简洁明了的代码了。

方法1

将该数的每位数用数组存起来,为了包含有 0 的情况,我们用倒序存储,再倒序组成两个数,判断这两个数后输出就好了。

核心代码
int temp=i;tot=0;
			while(temp!=0)
			{
				a[++tot]=temp%10;
				temp/=10;
			}
			int t=0;
			for(int j=tot;j>1;j--)
			{
				t*=10;t+=a[j];
				if(int(sqrt(t))*int(sqrt(t))==t)
				{
					int t1=0;
					for(int k=j-1;k>=1;k--)
						t1=t1*10+a[k];
					if(int(sqrt(t1))*int(sqrt(t1))==t1 && t1!=0)
					{
						printf("%d\n",i);
						break;
					}
				}
			}

方法2

将该数转换成字符串,再分成两个子串,然后转回整形,判断一下就可以输出了。这两个方法实际上是差不多的。

核心代码
string s=to_string(i);
for(int j=1;j<s.size();j++)
{
	string a=s.substr(0,j),b=s.substr(j);
	int aa=stoi(a),bb=stoi(b);
	if(int(sqrt(aa))*int(sqrt(aa))==aa && int(sqrt(bb))*int(sqrt(bb))==bb && bb!=0 && aa!=0)
	{
		printf("%d\n",i);
		break;
	}
}

代码实现

方法1

#include<bits/stdc++.h>
#define Sqrt(x) int(sqrt(x))//方便打字 
#define Z return
#define X 0
#define Y ;
using namespace std;
int a[10],tot;
int main()
{
	int l,r;
	scanf("%d%d",&l,&r);
	for(int i=l;i<=r;i++)
	{
		if(Sqrt(i)*Sqrt(i)==i)//是平方数 
		{
			int temp=i;tot=0;//存数组 倒序存储 
			while(temp!=0)
			{
				a[++tot]=temp%10;
				temp/=10;
			}
			int t=0;
			for(int j=tot;j>1;j--)//倒序组合 
			{
				t*=10;t+=a[j];//加上当前的一位数 重组第一个数 
				if(Sqrt(t)*Sqrt(t)==t)
				{
					int t1=0;
					for(int k=j-1;k>=1;k--)
						t1=t1*10+a[k];//重组第二个数 
					if(Sqrt(t1)*Sqrt(t1)==t1 && t1!=0)
					{
						printf("%d\n",i);
						break;
					}
				}
			}
		}
	}
	Z X Y//嘻嘻 
}

方法2

#include<bits/stdc++.h>
#define Sqrt(x) int(sqrt(x))//方便打字 
#define Z return
#define X 0
#define Y ;
using namespace std;
int a[10],tot;
int main()
{
	int l,r;
	scanf("%d%d",&l,&r);
	for(int i=l;i<=r;i++)
	{
		if(Sqrt(i)*Sqrt(i)==i)//是平方数 
		{
			string s=to_string(i);//转字符串 
			for(int j=1;j<s.size();j++)
			{
				string a=s.substr(0,j),b=s.substr(j);//拆成两个子串 
				int aa=stoi(a),bb=stoi(b);//转整形 
				if(Sqrt(aa)*Sqrt(aa)==aa && Sqrt(bb)*Sqrt(bb)==bb && bb!=0 && aa!=0)
				{
					printf("%d\n",i);
					break;
				}
			}
		}
	}
	Z X Y//嘻嘻 
}

THE END 

若还有什么要补充的或者修改的大佬请评论

  • 12
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值