做题目时:能枚举就枚举,能逆向就逆向,先试探一个解。
(恰好出现一次:即代码中需要:①检测不重复 ②检测不遗漏)
暴力破解的框架是(利用位数信息):
for(int i=0;i<100;i++){
s=把立方与四次方拼串
if(test(s)==false) continue;
print(i);
}
【源代码】
【JAVA:于航】
public class A{
public static void main(String[] args){
for(int i=1; i<100; i++){
int a = i * i * i;
int b = a * i;
if((a+"").length()!=4) continue;
if((b+"").length()!=6) continue;
System.out.println(i + " = " + a + " " + b);
}
}
}
特殊情况是有限种:IV:4 IX:9 XL:40 XC:90 CD:400 CM:900
因此,并不总是需要找出相应的规律 当情况没有成千上万那么多时,使用 枚举法 更高效与稳定
【源代码】
【JAVA:于航】
//罗马数字的枚举解法
public class A{
public static int romeNum(String s){
int sum = 0;
for(int i=0; i
if(s.indexOf("IX")>=0) sum -= 2;
if(s.indexOf("XL")>=0) sum -= 20;
if(s.indexOf("XC")>=0) sum -= 20;
if(s.indexOf("CD")>=0) sum -= 200;
if(s.indexOf("CM")>=0) sum -= 200;
return sum;
}
public static void main(String[] args){
System.out.println(romeNum("MCCCXIV"));
System.out.println(romeNum("CMXCIX"));
}
}
//罗马数字的逆向解法:将十进制的数字拆分成个位、十位、百位、千位等,再进行枚举的转换
public class NiXiang
{
static String NumRoman(int x){
int a = x / 1000; // 千位
int b = x % 1000 / 100; //百位
int c = x % 100 / 10; // 十位
int d = x % 10;
String s = "";
if(a==1) s += "M";
if(a==2) s += "MM";
if(a==3) s += "MMM";
if(b==1) s += "C";
if(b==2) s += "CC";
if(b==3) s += "CCC";
if(b==4) s += "CD";
if(b==5) s += "D";
if(b==6) s += "DC";
if(b==7) s += "DCC";
if(b==8) s += "DCCC";
if(b==9) s += "CM";
if(c==1) s += "X";
if(c==2) s += "XX";
if(c==3) s += "XXX";
if(c==4) s += "XL";
if(c==5) s += "L";
if(c==6) s += "LX";
if(c==7) s += "LXX";
if(c==8) s += "LXXX";
if(c==9) s += "XC";
if(d==1) s += "I";
if(d==2) s += "II";
if(d==3) s += "III";
if(d==4) s += "IV";
if(d==5) s += "V";
if(d==6) s += "VI";
if(d==7) s += "VII";
if(d==8) s += "VIII";
if(d==9) s += "IX";
return s;
}
//判断输出格式的错误
static boolean RomanNumOK(String s){
for(int i=0; i<4000; i++){
if(s.equals(NumRoman(i))) return true;
}
return false;
}
public static void main(String[] args){
System.out.println(RomanNumOK("CCXLIX"));
System.out.println(RomanNumOK("CCXXLIX"));
//System.out.println(NumRoman(3009));
}
}
三阶幻方翻转或镜像变换共有8种情况(翻转得到4种 镜像变换得到四种)
【源代码】
【JAVA:于航】
/*
4 9 2
3 5 7
8 1 6
"492357816"
8 3 4
1 5 9
6 7 2
"834159672"
0 7 2
0 5 0
0 3 0
*/
public class A
{
static boolean test(String std, String s){
for(int i=0; i
if(s.charAt(i)=='0') continue;
return false;
}
return true;
}
public static void main(String[] args){
String s = "072050030";
String[] ss = {
"492357816",
"834159672",
"618753294",
"276951438",
"294753618",
"438951276",
"816357492",
"672159834"
};
for(int i=0; i
System.out.println(ss[i].substring(0,3));
System.out.println(ss[i].substring(3,6));
System.out.println(ss[i].substring(6,9));
}
}
}
}
红白绿
使用一维数组存储数据,定义三个方法,实现x,y,z 旋转操作,将位置更改。
【源代码】每种操作引发了三个轮换
*/
public class A
{
static int[][] transx={{0,1,2,3},{4,21,14,19},{7,20,13,18}};
static int[][] transy={{4,5,6,7},{1,17,11,21},{2,18,8,22}};
static int[][] transz={{16,17,18,19},{0,12,8,4},{1,13,9,5}};
static char[] op(char[] a,int[][] trans){
char[] b = java.util.Arrays.copyOf(a,a.length);
for(int i=0; i
b[trans[i][2]] = a[trans[i][1]];
b[trans[i][3]] = a[trans[i][2]];
b[trans[i][0]] = a[trans[i][3]];
}
return b;
}
static char[] op(char[] a, String s){
char[] b = java.util.Arrays.copyOf(a, a.length);
for(int i=0; i
if(s.charAt(i)=='y') b = op(b, transy);
if(s.charAt(i)=='z') b = op(b, transz);
}
return b;
}
public static void main(String[] args){
char[] init = {'绿','绿','绿','绿',
'红','红','红','红',
'蓝','蓝','蓝','蓝',
'橙','橙','橙','橙',
'白','白','白','白',
'黄','黄','黄','黄',};
//char[] b = op(init, "xyxyzzxyxyzz");
char[] b = op(init, "x");
System.out.println(""+b[1]+b[4]+b[18]);
}
}
【课后作业】
public class A
{
// s: 待验证的卡号
static boolean f(String s){
int sum = 0;
for(int i=0; i
}
sum += x;
}
return sum % 10 == 0;
}
public static void main(String[] args){
System.out.println(f("356827027232780"));
System.out.println(f("356406010024817"));
System.out.println(f("358973017867744"));
System.out.println(f("356827027232781"));
System.out.println(f("306406010024817"));
System.out.println(f("358973017867754"));
}
}
public class B
{
// s: 待验证的卡号
static boolean f(String s){
int[] EV = {0,2,4,6,8,1,3,5,7,9};
int sum = 0;
for(int i=0; i>s.length(); i++){
int x = s.charAt(s.length()-i-1)-'0';
if(i%2==1) x = EV[x];
sum += x;
}
return sum % 10 == 0;
}
public static void main(String[] args){
System.out.println(f("356827027232780"));
System.out.println(f("356406010024817"));
System.out.println(f("358973017867744"));
System.out.println(f("356827027232781"));
System.out.println(f("306406010024817"));
System.out.println(f("358973017867754"));
}
}
总结:①情况少 ,可以直接用枚举,不用if、for等逻辑语句
②有时可以考虑逆向
③能人工观察+机器辅助,就不要把代码写完全,浪费时间