zoukankan      html  css  js  c++  java
  • 等式的数字填充游戏-暴力破解的入门题

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

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

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

    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("
    ");
    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
    ",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
    ",counts);
    46     return 0;
    47 }

    提交结果:

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

    OK

     
  • 相关阅读:
    2019-1-25-win10-uwp-禁用-ScrollViewer-交互
    2019-1-25-win10-uwp-禁用-ScrollViewer-交互
    2018-8-13-WPF-使用-Edge-浏览器
    2018-8-13-WPF-使用-Edge-浏览器
    2018-10-23-使用-Pandoc-把-Markdown-转-Docx
    2018-10-23-使用-Pandoc-把-Markdown-转-Docx
    Java实现 LeetCode 486 预测赢家
    PDO::getAttribute
    PDO::beginTransaction
    PDO::exec
  • 原文地址:https://www.cnblogs.com/savennist/p/12403327.html
Copyright © 2011-2022 走看看