凑平方数
把0~9这10个数字,分成多个组,每个组恰好是一个平方数,这是能够办到的。
比如:0, 36, 5948721
再比如:
1098524736
1, 25, 6390784
0, 4, 289, 15376
等等...
注意,0可以作为独立的数字,但不能作为多位数字的开始。
分组时,必须用完所有的数字,不能重复,不能遗漏。
如果不计较小组内数据的先后顺序,请问有多少种不同的分组方案?
注意:需要提交的是一个整数,不要填写多余内容。
思路:将所有平方数根据其长度放入不同的组合中,我是用的set来装,然后就是每个位数组合开始遍历;注意每个分组方案中为了防止相同组合不同次序这种情况,所有我们遍历时排一个序,然后就是DFS的事了。说实话这个题调试了很久,原先我一直以为11的倍数一定不是满足条件的,这个主观认识直接导致数据减少了很多。
#include<iostream> #include<cstdio> #include<set> #include<string> #include<string.h> using namespace std; #define ll long long int flag[10] = { 0 }; set<string>se[11]; ll sum = 0; bool isOne(string str) { memset(flag, 0, sizeof(flag)); for (int i = 0; i < str.length(); i++){ if (str[i] == ' ')continue; if (flag[str[i] - '0'] == 0) flag[str[i] - '0'] = 1; else return false; } return true; } void dfs(int len, int p, ll sp = 9876543210 , string str = "") { //cout << "sp = " << sp << endl; if (len == 10){ if (isOne(str)){ sum++; printf("%3d : ", sum); cout << str << endl; } return; } for (int i = p; i >=1; i--){ set<string>::iterator iter; for (iter = se[i].begin(); iter != se[i].end(); iter++){ ll temp = atoi((*iter).c_str()); if (temp >= sp)break; if (isOne(str + *iter)){ //cout << " len = " << len << " " << sp << " ?= " << *iter << endl; dfs(len + i, i, temp, str + " " + *iter); } } } } int main() { for (ll i = 0; i*i <= 9876543210; i++){ string temp = to_string(i*i); if (isOne(temp)){ int cnt = temp.length(); se[cnt].insert(temp); } } dfs(0, 10); cout << "sum = " << sum << endl; return 0; }