其实这个题目我一直没想好应该叫什么,就是在做蓝桥杯的时候会遇到很多的题,给你一等式,abcdef...分别是1-9(||12||15)不重复问你有几种方案?

  我之前一直都是用的for循环在做,听说这叫什么暴力破解还是枚举法的。小白不是很懂这些。

  但是之前做过一道题,好像就是15个数的for循环写的,一个是巨累(因为我用a!=b&&a!=c&&a!=....真的特别多而且容易写错),另一个是我记得我这道题写了很久最后提交没有分数,因为!!!超时了!!!

  真的特别气,当时的我只会做一种题就是for循环的这个,我觉得自己要凉凉了,唯一会的题还超时了。所以痛定思痛,自己去网上down了全排列+dfs的代码。

  恰巧这次的代码特别合适,我竟然看懂了(我以前也百度过,但是不记得为什么没有看懂,坚信我们for循环可以打天下的一直没有再去看),而且真的是要特别的夸一夸这一套代码,因为我之后所以的这种题,靠的都是这一套代码。特别省事,差不多可以算是我唯一的模板了。

  昨天的题有一道这样的,然后就想把我会的所有的方法整理出来,当然,模板万岁啊。但是如果有时间走两套程序的话,算是检查了,保证准确率。

 标题: 马虎的算式

小明是个急性子,上小学的时候经常把老师写在黑板上的题目抄错了。

有一次,老师出的题目是:36 x 495 = ?

他却给抄成了:396 x 45 = ?

但结果却很戏剧性,他的答案竟然是对的!!

因为 36 * 495 = 396 * 45 = 17820

类似这样的巧合情况可能还有很多,比如:27 * 594 = 297 * 54

假设 a b c d e 代表1~9不同的5个数字(注意是各不相同的数字,且不含0)

能满足形如: ab * cde = adb * ce 这样的算式一共有多少种呢?(满足乘法交换律的算式计为不同的种类,所以答案肯定是个偶数。)

第一种方法:最简单的for循环法。最起码10以内很简单不会超时,只要仔细就不会出错

 public class Main {

     public static void main(String[] args) {
//2.能满足形如:ab * cde = adb * ce这样的算式一共有 ?种
int a,b,c,d,e;
int count=0;
for(a=1;a<10;a++){
for(b=1;b<10;b++){
for(c=1;c<10;c++){
for(d=1;d<10;d++){
for(e=1;e<10;e++){
int x=(10*a+b)*(100*c+10*d+e);
int y=(100*a+10*d+b)*(10*c+e);
if(x==y&&
a!=b&&a!=c&&a!=d&&a!=e&&
b!=a&&b!=c&&b!=d&&b!=e&&
c!=a&&c!=b&&c!=d&&c!=e&&
d!=a&&d!=b&&d!=c&&d!=e&&
e!=a&&e!=b&&e!=c&&e!=d ){
count++;
}
}
}
}
}
}
System.out.println(count); } }

ps:谁能想到,我第一次这个题写错了呢,因为我忽略了这句话,忘了判断是否是不同的数字了。--->假设 a b c d e 代表1~9不同的5个数字(注意是各不相同的数字,且不含0)在一个是,我看到题目中说--->满足乘法交换律的算式计为不同的种类,所以答案肯定是个偶数。我做的时候没有判断是否不同数字,所以答案是1007,所以,我看到这句话,更加确定了,我做的真对啊。我以为他这句话是在提醒我,*2啊*2啊。结果当然是错的啦。他写这句话应该就是单纯的帮你减轻负担啊,不用考虑交换律的问题,这样出来多少就是多少了。

第二种方法:for循环法稍作改变。新建一个used数组,分别对应1 2 3 4.。。9然后用used数组的值标记是否使用过了。记得在这一轮的for循环最后释放哦。

 public class Main {

     public static void main(String[] args) {
//2.能满足形如:ab * cde = adb * ce这样的算式一共有 ?种
int a,b,c,d,e;
int count=0;
int []used=new int[11];
for(int i=1;i<10;i++){
used[i]=0;//0标记没有用过 1标记用过了
}
for(a=1;a<10;a++){
used[a]=1;
for(b=1;b<10;b++){
if(used[b]==1)continue;
used[b]=1;
for(c=1;c<10;c++){
if(used[c]==1)continue;
used[c]=1;
for(d=1;d<10;d++){
if(used[d]==1)continue;
used[d]=1;
for(e=1;e<10;e++){
if(used[e]==1)continue;
used[e]=1;
int x=(10*a+b)*(100*c+10*d+e);
int y=(100*a+10*d+b)*(10*c+e);
if(x==y){
count++;
}
used[e]=0;
}
used[d]=0;
}
used[c]=0;
}
used[b]=0;
}
used[a]=0;
}
System.out.println(count); }

这里再备注一下,其实used直接建Boolean比较好,用false true,这样if判断的时候 就不用特意去写了。我这个是因为 我一开始用的boolean 运行的时候有错误,当时做的很烦躁就直接改了int 。之后在别的里面试了boolean完全可以没有问题,可能是其他的地方不知道那里报错了。

第三种方法:全排列+dfs

我其实一开始忘了这个办法,然后翻之前的笔记找到的。先写一下笔记上的原题:

A+B/C+DEF/GHI=0,A-I为1-9不重复,求有几种可满足式子。(DEF=D*100+E*10+F...)

 public class Main {
static int count=0;
public static void main(String[] args) {
// TODO Auto-generated method stub
float a[]=new float[10];
boolean visit[]=new boolean[10];
dfs(a,visit,1);
System.out.println(count);
}
private static void dfs(float[]a,boolean[]visit,int num){
if(num==10){
if(judge(a)){
count++;
}
return;
}
for(a[num]=1;a[num]<10;a[num]++){
if(visit[(int)a[num]]==false){
visit[(int)a[num]]=true;
num=num+1;
dfs(a,visit,num);
num=num-1;
visit[(int)a[num]]=false;
}
}
}
private static boolean judge(float[]a){
float A=a[1];
float B=a[2]/a[3];
float C=a[4]*100+a[5]*10+a[6];
float D=a[7]*100+a[8]*10+a[9];
if(A+B+C/D==10){
return true;
}
return false;
} }

然后根据这个写了这道马虎的算式的代码:

 public class Main {
//2.能满足形如:ab * cde = adb * ce这样的算式一共有 ?种
static int count=0;
public static void main(String[] args) {
// TODO Auto-generated method stub
float a[]=new float[6];//数组长度由题目中的变量个数决定abcde 5
boolean visit[]=new boolean[10];
dfs(a,visit,1);
System.out.println(count);
}
private static void dfs(float[]a,boolean[]visit,int num){
if(num==6){//==前面数组长度
if(judge(a)){
count++;
}
return;
}
for(a[num]=1;a[num]<10;a[num]++){
if(visit[(int)a[num]]==false){
visit[(int)a[num]]=true;
num=num+1;
dfs(a,visit,num);
num=num-1;
visit[(int)a[num]]=false;
}
}
}
private static boolean judge(float[]a){
//这一块根据题目自己写
//1 2 3 4 5
//a b c d e
float A=a[1]*10+a[2];
float B=a[3]*100+a[4]*10+a[5];
float C=a[1]*100+a[4]*10+a[2];
float D=a[3]*10+a[5];
if(A*B==C*D){
return true;
}
return false;
} }

这个全排列真的挺好用的,而且记住这个模板在做题特别省时间!!而且可以说完全不用过脑子了。

因为为了统一,a[]我就延续用了float,因为这种题真的就是来来回回的*||/所以 用float更放心一些。

补充:

1.拿浮点数进行暴力破解很危险啊,因为浮点数计算有误差!!!

double a =1.0;

double b=0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1;

输出a,b;得到的值是 a->1.0  b->0.999999999999

所以!如果sysout(a==b);必然是false。

2.那么怎么去比较呢?

  1.比较a-b是否小于一个比较小的数

System.out.println(Math.abs(a-b)<1e-6);

  2.避开浮点数,等式两边同时扩大。

  eg:求a*2.3+b*1.9==82.3可以转化成a*23+b*19==823

3.举例:浮点数的运算可以通过变换形式进行

???1/4=0   ==> int/int=int 所以0.25=>(int)0.25=>0

所以,1/a+1/b+1/c=1循环求解的时候可以

  1.  1.0/a+1.0/b+1.0/c=1.0    =>这个方法就避免了上面说的int/int =int

  2.     bc+ac+ab=abc  =>这样一转换,就和浮点数没有关系了,就不会影响了

4.举例:特殊值举例

 System.out.println(3/0);
System.out.println(3.0/0);

执行第一行,输出:0不能为分母的英文,报错

执行第二行,输出:Infinity,即无穷大。

why???因为第二行 =>3.0是浮点数(double/float),所以0=>看作了一个0.00000000000....就是一个很很很小的数。3.0/一个很很很小的数===>无穷大

      double a=3.0/0;
System.out.println(a+1);
System.out.println(a+a);
System.out.println(1/a);
System.out.println(1/(-a));
System.out.println(a-a);

输出为:

Infinity
Infinity
0.0
-0.0
NaN

NaN=>not a number,不是一个数值。类似于小学说的无意义。当然NaN+||-一个数也都=NaN

5.任意精度问题(当float 不够->double,double不够?)

举例:有效数字100位(如1/6)

     BigDecimal a=BigDecimal.valueOf(1).divide(BigDecimal.valueOf(6),new MathContext(100));
System.out.println(a);

输出:0.1666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666667

正好做到这里插一个黄金连分数的题当例题了。

 import java.math.BigDecimal;
import java.math.MathContext; public class Main {
public static void main(String[] args) {
// TODO Auto-generated method stub
BigDecimal bd = new BigDecimal(1);
for (int i = 0; i < 10000; i++) {
bd = bd.add(BigDecimal.ONE);
// bd = BigDecimal.ONE.divide(bd, 100, BigDecimal.ROUND_HALF_DOWN);
bd = BigDecimal.ONE.divide(bd, new MathContext(100));
}
System.out.println(bd.toString());
}
}

输出:0.6180339887498948482045868343656381177203091798057628621354486227052604628189024497072072041893911375

10 11两行都可以用,答案都是对的。

嗯嗯,终于完成今天的任务了。本来没想写关于浮点数的这些的,没想到写着写着就这么多了。啊,马上10点了,溜了溜了。

for循环枚举法,全排列+dfs,补充浮点数注意事项的更多相关文章

  1. 回溯法、DFS

    回溯法 为了求得问题的解,先选择某一种可能情况向前探索,在探索过程中,一旦发现原来的选择是错误的,就退回上一步重新选择条件,继续向前探索,如此反复进行,直至得到解或证明无解. DFS DFS模板 vo ...

  2. OpenJudge计算概论-完美立方【暂时就想到了枚举法了】

    /*===================================== 完美立方 总时间限制: 1000ms 内存限制: 65536kB 描述 a的立方 = b的立方 + c的立方 + d的立 ...

  3. 算法:枚举法---kotlin

    枚举法:效率低,循环所有的情况,找到正确答案 用于解决数学问题,还是很简单的. 比如,奥数里面: 算 法 描 述 题X题=题题题题题题 其中 算法描述题每一个为一个数字,请写出正确的数字. ok,我们 ...

  4. OpenJudge计算概论-比饭量【枚举法、信息数字化】

    /*====================================================================== 比饭量 总时间限制: 1000ms 内存限制: 655 ...

  5. 【NYOJ-187】快速查找素数—— 枚举法、筛选法、打表法

    快速查找素数 时间限制:1000 ms  |  内存限制:65535 KB 难度:3   描述 现在给你一个正整数N,要你快速的找出在2.....N这些数里面所有的素数. 输入 给出一个正整数数N(N ...

  6. 谁是嫌疑犯问题Python枚举法

    原文:https://blog.csdn.net/yunzifengqing/article/details/81941592 问题描述:有6名犯罪嫌疑人A.B.C.D.E.F,已知如下事实: A.B ...

  7. 全排列——DFS实现

    原创 之间就写过一篇全排列的博客:https://www.cnblogs.com/chiweiming/p/8727164.html 详细介绍请回看,用的方法(暂且就叫)是“交换法”,其实思路就是DF ...

  8. 组合数学(全排列)+DFS CSU 1563 Lexicography

    题目传送门 /* 题意:求第K个全排列 组合数学:首先,使用next_permutation 函数会超时,思路应该转变, 摘抄网上的解法如下: 假设第一位是a,不论a是什么数,axxxxxxxx一共有 ...

  9. OpenJudge计算概论-称体重【枚举法、信息数字化】

    /*====================================================================== 称体重 总时间限制: 1000ms 内存限制: 655 ...

随机推荐

  1. C#获取类里面的所有的方法名称

    Type trypInfo = typeof(Program);// Program为类名//获得方法名string str = "包括的方法名列表:\r\n"; MethodIn ...

  2. Python下载与安装

    Python目前已支持所有主流操作系统,在Linux,Unix,Mac系统上自带Python环境,一般默认装的是Python2版本,Windows系统上没有Pyhton环境,需要我们手动安装一下,过程 ...

  3. 自定义信息丰富的Android Log

    [问题背景] 最近在项目上需要用LOG来查看和定位一些信息,但是系统原生的LOG实在太乱,信息也不太多,比如调用行数,所在方法,所在类名,线程名称都没有. [初步想法] 本着开源的精神,首先去GitH ...

  4. 【POJ1509】Glass Beads 【后缀自动机】

    题意 给出一个字符串,求它的最小表示法. 分析 这个题当然可以用最小表示法做啦!但是我是为了学后缀自动机鸭! 我们把这个字符串长度乘二,然后建SAM,然后在SAM上每次跑最小的那个字母,找出长度为n的 ...

  5. SpringBoot30 整合Mybatis-Plus、整合Redis、利用Ehcache实现二级缓存、利用SpringCache和Redis作为缓存

    1 环境说明 JDK: 1.8 MAVEN: 3. SpringBoot: 2.0.4 2 SpringBoot集成Mybatis-Plus 2.1 创建SpringBoot 利用IDEA创建Spri ...

  6. hdcloud SOA架构

    SOA是一个范式   多租户技术 一个租户可以是任何一个应用--或者是企业内部应用,或外部应用,它需要有自己的安全的和排他的虚拟计算环境.该环境包含了从存储到用户界面的所有或者某些选定的企业架构层.所 ...

  7. 1、设备网络SDK主要功能

    图像预览.文件回放和下载,云台控制,布防/撤防,语音对讲,日志管理,解码卡,远程升级,远程重启/关闭,格式化硬盘,参数配置(系统配置,通道配置,串口配置,报警配置,用户配置),多路解码器,智能设备功能 ...

  8. ORACLE 异机恢复

    有时候需要将大的数据库发布到客户现场或转移机器时,不得不考虑在异机上恢复已经调整.测试好的库. dumpdp 全备的方法虽然易用,但在处理对象.索引.空间的时候异常的出错,比如:见有些公司,建表.索引 ...

  9. vs2015发布网站至azure web应用服务

    进入www.azure.cn管理门户 1,左下角新建web应用,实例如下,url设置为demo(有防止重名判断) 2,进入demo配置页(左侧web应用下点击demo) 3,demo首页,下载配置文件 ...

  10. 说说JVM中的操作码

    JVM操作码 加载与存储操作码 load --从局部变量加载值到栈上 ldc --从池中加载常量到栈上 store --把值从栈中移走,存到局部变量中 dup --复制栈顶的值 getField -- ...