[蓝桥杯 2014 国 C] 拼接平方数
题目描述
小明发现 49 49 49 很有趣,首先,它是个平方数。它可以拆分为 4 4 4 和 9 9 9,拆分出来的部分也是平方数。 169 169 169 也有这个性质,我们权且称它们为:拼接平方数。
100 100 100 可拆分 1 , 00 1,00 1,00,这有点勉强,我们规定, 0 , 00 , 000 0,00,000 0,00,000 等都不算平方数。
小明想:还有哪些数字是这样的呢?
你的任务出现了:找到某个区间的所有拼接平方数。
输入格式
两个正整数 a , b ( a < b < 1 0 6 ) a,b(a<b<10^6) a,b(a<b<106)。
输出格式
若干行,每行一个正整数。表示所有的区间 [ a , b ] [a,b] [a,b] 中的拼接平方数,从小到大输出。
样例 #1
样例输入 #1
169 10000
样例输出 #1
169
361
1225
1444
1681
3249
4225
4900
9025
提示
时限 1 秒, 256M。蓝桥杯 2014 年第五届国赛
思路
首先定义两个集合sq
和ans
,其中sq
用来保存平方数,ans
用来保存满足条件的拼接平方数。然后从输入中读取两个数a
和b
,这两个数定义了需要查找的区间。
接着,进行预处理,计算所有小于等于b
的平方数,将结果保存到集合sq
中。这里使用了sqrt(b)
来限定循环的上界,减少了不必要的计算。
在预处理完毕后,开始遍历集合sq
,对于每一个元素,将其转换为字符串s1
,然后再次遍历集合sq
,将元素转换为字符串s2
。在这个过程中,尝试将s1
和s2
进行拼接,并将结果转换为整数c
。
如果c
大于b
,则终止当前循环,因为后续的拼接结果都会大于b
。如果c
在区间[a, b]
内,并且c
是平方数(即sq
集合中存在c
),则将c
添加到集合ans
中。
在这个过程中,s2
会不断地在前面添加0
,直到拼接结果的长度超过8
时停止循环,防止出现std::out_of_range
的错误。
最后,遍历集合ans
,将其中的元素按照升序输出,这就是所有满足条件的拼接平方数。
AC代码
#include <algorithm>
#include <cmath>
#include <iostream>
#include <set>
#define AUTHOR "HEX9CF"
using namespace std;
using ll = long long;
const int N = 1e6 + 7;
const int INF = 0x3f3f3f3f;
const ll MOD = 1e9 + 7;
int n;
set<int> sq, ans;
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int a, b;
cin >> a >> b;
for (int i = 1; i <= sqrt(b); i++) {
sq.insert(i * i);
// cout << i * i << endl;
}
for (auto it1 = sq.begin(); it1 != sq.end(); it1++) {
string s1 = to_string(*it1);
for (auto it2 = sq.begin(); it2 != sq.end(); it2++) {
string s2 = to_string(*it2);
while (1) {
string s = s1 + s2;
// cout << s << endl;
if (s.length() > 8) {
// 防止std::out_of_range
break;
}
int c = stoi(s);
if (c > b) {
break;
}
if (c >= a && c <= b && sq.count(c)) {
// cout << *it1 << " " << *it2 << " " << c << endl;
ans.insert(c);
}
// 第二个平方数可以有前导零
s2 = "0" + s2;
}
}
}
for (const auto i : ans) {
cout << i << "\n";
}
return 0;
}