蓝桥杯 16决赛 A2 凑平方数(锁定数据范围)
凑平方数
把0~9这10个数字,分成多个组,每个组恰好是一个平方数,这是能够办到的。
比如:0, 36, 5948721
再比如:
1098524736
1, 25, 6390784
0, 4, 289, 15376
等等…
注意,0可以作为独立的数字,但不能作为多位数字的开始。
分组时,必须用完所有的数字,不能重复,不能遗漏。
如果不计较小组内数据的先后顺序,请问有多少种不同的分组方案?
==========================
思路:
找出可能出现的平方数
dfs得到组合数
剪枝,组合数是真的大
总结
long l =990000000; ->The literal xxxxxxxxxx of type int is out of range->long l =xxxL就可了
我的第一个想法->嵌套dfs(组合方式+切分方式),问题就是太慢了,要好几分钟,作为一个 经典的错误案例
Double.isNaN(double d) -true非数字(指的是"78a"," 57"可以被解析成数字,“5 7”/" "不可以)
public class Test{
static ArrayList<String> list =new ArrayList<String>();
static boolean[] vis =new boolean[10];
static int ans;
public static void main(String[] args) {
//System.out.println(Integer.MAX_VALUE); //2147483647
long bound =(long)Math.pow(Double.parseDouble("9876543210"), 0.5);
for(long l =0L ;l <=bound ;l ++) if(!isRe(l *l)) list.add(l *l +"");
//排列组合
dfs(0 ,0);
//输出结果
System.out.println(ans);
}
private static boolean isRe(long l) {
char[] a =(l +"").toCharArray();
for(int i =0 ;i <a.length ;i ++) for(int j =i +1 ;j <a.length ;j ++) if(a[i] ==a[j]) return true;
return false;
}
private static void dfs(int index ,int numb) {
if(numb ==10) {ans ++; return;}
char[] tmp =null;
boolean isVis =false;
for(int i =index ;i <list.size() ;i ++) {
tmp =list.get(i).toCharArray();
//串长是否合法
if(numb +tmp.length >10) continue;
//数字是否使用
isVis =false;
for(int j =0 ;j <tmp.length ;j ++) if(vis[tmp[j] -48]) {isVis =true; break;}
if(isVis) continue;
//标记使用数字
for(int j =0 ;j <tmp.length ;j ++) vis[tmp[j] -48] =true;
dfs(i +1 ,numb +tmp.length);
//回溯
for(int j =0 ;j <tmp.length ;j ++) vis[tmp[j] -48] =false;
}
}
}