等式的数字填充游戏-暴力破解的入门题

在暴力破解的相关题型中常常见到一种数字填充使等式成立的题目。这一类题目一般情况下又两种解法。

------------分割线君------------

其中一种是逐个变量进行可能性遍历。在这种方法中,我们的注意力主要集中在以下几点:

1、哪些未知量需要遍历?按照什么样的顺序进行遍历才能在循环层数最少的情况下算出结果?

2、对于某一个需要遍历的未知量,其遍历起点、终点各是什么?

3、后遍历的未知量是否受到前遍历未知量的限制?比如范围、形式、是否相等或是否有数字重复;

4、使用怎样的条件可以尽可能的减少循环次数,提高效率?

5、最终的判断成立的条件是什么?怎么记录?

一般情况下,这种题目都是多层循环嵌套及其相关分析。做这种题目时,一定要先对遍历循环层数有一个大致的描述,确定复杂程度。这是必须清醒的认识到的。

------------分割线君------------

第二种解法往往见于填入数字已经确定且要求不重复的特殊情形下。在这种情况下,上述遍历虽然有可行性,但往往复杂度太高。而出题人的中心基本落在 暴力+排列组合 上。此时,就可以通过algorithm头文件中的next_permutation()函数进行开快速遍历。同时,将解题重心放在 如何对某一序列的各个元素进行组合 上。此时需要考虑的是组合形式与验证方案。值得一提的是,对于0到9这是个数字,遍历其全排列的过程并不缓慢。对于计算机来说是相当迅速的。

------------分割线君------------

下面是蓝桥杯的一个真题。

问题描述
100 可以表示为带分数的形式:100 = 3 + 69258 / 714。
还可以表示为:100 = 82 + 3546 / 197。
注意特征:带分数中,数字1~9分别出现且只出现一次(不包含0)。
类似这样的带分数,100 有 11 种表示法。

输入格式
从标准输入读入一个正整数N (N<1000*1000)

输出格式
程序输出该数字用数码1~9不重复不遗漏地组成带分数表示的全部种数。
注意:不要求输出每个表示,只统计有多少表示法!
我注:表示形式N=a+b/c

利用第二种方案进行解答时,我们仅仅需要考虑如何组合数字并验证即可。而如果使用第一种方案,虽然可能在N较小的情况下比较迅速,但是随着N的增大,遍历的复杂度会急剧增大。可以很容易的看出,分数中分子和分母的大小可以远远超过N的大小,这使得遍历更加复杂。

使用第二种方案:我发现分数一定时可以约分成整数的。所以分子一定比分母大。(并不严谨的)换句话说,就是分子的位数不能小于分母。这时,我可以先对分解式中的a确定一个位数,并从排列中分配其对应个数的数字。然后将剩余的数字分配。最后验证即可。内层循环的结束条件是:当分母的分不到数字时,结束内层循环。

代码:

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<iostream>
 4 #include<algorithm>
 5 using namespace std;
 6 int counts;
 7 int num[10];
 8 int n;
 9 
10 int main()
11 {
12     for(int i=1;i<10;i++)
13     {
14         num[i-1]=i;
15     }//填充9个数字
16     cin>>n;
17     //int s=500;
18     do
19     {
20         //s--;
21         //for(int i=0;i<9;i++)printf("%d ",num[i]);
22         //printf("\n");
23         //
24         int cur=0;
25         int a=0,b=0,c=0;
26         for(int i=1;i<=9;i++)
27         {
28             for(;cur<i;cur++)a=a*10+num[cur];//获取a
29             if(a>=n)break;
30             //
31             int wei=9-i;//剩余的数字个数
32             int weic=wei/2;//c的最大位数
33             for(;weic;weic--)
34             {
35                 int weib=wei-weic;//b的位数
36                 for(;cur<i+weic;cur++)c=c*10+num[cur];
37                 for(;cur<9;cur++)b=b*10+num[cur];
38                 //printf("%d-%d-%d\n",a,b,c);
39                 if((n-a)*c==b)counts++;
40                 b=0,c=0,cur=i;
41             } 
42         }
43         //
44     }while(next_permutation(num,num+9));
45     printf("%d\n",counts);
46     return 0;
47 }

提交结果:

  带分数 03-03 16:42 829B C++ 正确 100 31ms 2.503MB

OK

 
posted @ 2020-03-03 17:09  SavenNeer  阅读(356)  评论(0编辑  收藏  举报