在算法竞赛中,很多问题是来不及用数学公式推导出来的。或者说根本就找不到数学规律,这时我们就需要使用枚举来暴力破解。

不过枚举也是需要脑子的,一味的暴力只能超时。因此我这里选择了几道mooc上经典的题目来做复习。

1、完美立方。

  思路:

  从2到N枚举a的值,2到a枚举d的值,2到d的枚举b的值,2到c枚举b的值。当

  1.   满足a*a*a==b*b*b+c*c*c+d*d*d
      的时候对结果输出。
      代码如下:
  1. #include <iostream>
  2.  
  3. using namespace std;
  4. int main() {
  5. int N;
  6. cin>>N;
  7. for(int a=;a<=N;a++){
  8. for(int d=;d<=a;d++){
  9. for(int c=;c<=d;c++){
  10. for(int b=;b<=c;b++){
  11. if(a*a*a==b*b*b+c*c*c+d*d*d) cout<<"Cube = "<<a<<", Thiple = ("<<b<<","<<c<<","<<d<<")"<<endl;
  12. }
  13. }
  14. }
  15. }
  16. return ;
  17. }

运行结果如下:

2、生理周期

  1. 做此题我们首先会有个思路就是从d+1开始一个一个尝试,直至满足条件(
  1. (k-p)%23==0&&(k-e)%28==0&&(k-i)%33==0)
    所以我们很轻易地就能写出对应的代码。代码如下:
  1. #include <iostream>
  2. using namespace std;
  3. int main(){
  4. int p,e,i,d,N=;
  5. while(cin >> p >> e >> i >> d&&p!=-) {
  6. int k;
  7. for(k=d+;(k-p)%||(k-e)%||(k-i)%;k++);
  8. cout<<"Case "<<++N<<": The next triple peak occurs in "<<k-d<<" days."<<endl;
  9. }
  10. return ;
  11. }
  1. 不过在此我们是否会有个疑问。一个一个的尝试是否过于浪费时间了?
    这里我们给出另一种思路。
    我们先枚举出k+1后,第一个满足高峰的时间点作为第一种高峰的基数,这时我们需要等到k-p%23==0的时候停止。
    这时的k代表着满足了k-p
    然后我们枚举下一种高峰的时间基数。这次我们每次只需要+23就够了。因为23以内肯定不满足第一种高峰。
    随后我们再枚举第三个满足高峰的时间点的基数,这个基数-d就是我们最终的答案,这次我们每次跳过23*28个单位即可。
    总体代码如下所示。
  1. #include <iostream>
  2. using namespace std;
  3. int main(){
  4. int p,e,i,d,N=;
  5. while(cin >> p >> e >> i >> d&&p!=-) {
  6. int k;
  7. for(k=d+;(k-p)%;k++);//c++中正数就是true
  8. for(;(k-e)%;k+=);
  9. for(;(k-i)%;k+=*);
  10. cout<<"Case "<<++N<<": The next triple peak occurs in "<<k-d<<" days."<<endl;
  11. }
  12. return ;
  13. }
  1.  
  2. 运行结果如下。

3、POJ1013 Counterfeit Dollar(mooc中称硬币)

题目链接

 这题目不难,但是这道题我WA了很多次。其中我说下WA的原因:

1.每个盘子称的牌子不一定有4个。

2.如果某个假币可能轻可能重,不要continue,要以heavy----light的俩次形式输出。

思路:

定义一个大小为9字符串数组。作为每次输入的字符串。

依次假设每个硬币为假的。然后从重到轻挨个枚举,当找到假币的时候输出。

下面是AC代码:

  1. #include <iostream>
  2. #include <string>
  3. #include <map>
  4.  
  5. using namespace std;
  6. int main(){
  7. int N;
  8. cin>>N;
  9. map<char,int> m;
  10. for(int i=;i<;i++) {
  11. m[(char)i]=;
  12. }
  13. while(N--){
  14. string str[];
  15. cin>>str[]>>str[]>>str[]>>str[]>>str[]>>str[]>>str[]>>str[]>>str[];
  16. for(int i=;i<;i++){
  17. int sign = ;
  18. int left = ,right = ;
  19. string res="";
  20. m[(char)i]=;
  21. for(int k=;k<;k++) {
  22. for (int j = ; j < str[+*k].length(); j++)left += m[str[+*k][j]];
  23. for (int j = ; j < str[+*k].length(); j++)right += m[str[+*k][j]];
  24. if (left == right) res = "even";
  25. if (left > right) res = "up";
  26. if (left < right) res = "down";
  27. if (res == str[+*k])sign++;
  28. left=;
  29. right=;
  30. }
  31. if(sign==)cout<<(char)i<<" is the counterfeit coin and it is heavy.\n";
  32.  
  33. sign=;
  34. res="";
  35. m[(char)i]=-;
  36. for(int k=;k<;k++) {
  37. for (int j = ; j < str[+*k].length(); j++)left += m[str[+*k][j]];
  38. for (int j = ; j < str[+*k].length(); j++)right += m[str[+*k][j]];
  39. if (left == right) res = "even";
  40. if (left > right) res = "up";
  41. if (left < right) res = "down";
  42. if (res == str[+*k])sign++;
  43. left=;
  44. right=;
  45. }
  46. if(sign==) cout<<(char)i<<" is the counterfeit coin and it is light.\n";
  47.  
  48. m[(char)i]=;
  49. }
  50. }
  51. return ;
  52. }

4、EXTENDED LIGHTS OUT(POJ 1222)

题目链接

这道题着实有点难。不过我们这次用枚举的方法解答这个问题。

分析:

输入一个5*6的矩阵,让我们从中选取一个按钮方案,使最终所有灯都熄灭。

思路:

0、目标使所有灯的状态变为0。

1、想不干扰第1行别的灯的状态来改变第1行,就需要按下面的按钮才能准确的改变。

2、别的行数也是以此类推。

3、这样别的行数的状态都会随着第一行的变化而确定。

AC代码如下:

  1. #include <iostream>
  2. using namespace std;
  3. int Matrix[][];
  4. int res[][];
  5. int temp[][];
  6. void Flip(int &a){
  7. if(a) a=;
  8. else a=;
  9. }
  10. bool Check(){
  11. for(int i=;i<;i++){
  12. if(temp[][i]) return false;
  13. }
  14. return true;
  15. }
  16. void print(int t){
  17. cout<<"PUZZLE #"<<t<<endl;
  18. for(int i=;i<;i++){
  19. for(int j=;j<;j++) {
  20. if(j==)cout<<res[i][j];
  21. else cout << res[i][j] << " ";
  22. }
  23. cout<<endl;
  24. }
  25. }
  26. int main(){
  27. int N;cin>>N;
  28. for(int t=;t<=N;t++){
  29. for(int i=;i<;i++)for(int j=;j<;j++)cin>>Matrix[i][j];//输入矩阵
  30. for(int a=;a<;a++)for(int b=;b<;b++)for(int c=;c<;c++)for(int d=;d<;d++)for(int e=;e<;e++)for(int f=;f<;f++){
  31. int A[] = {a,b,c,d,e,f};
  32. for(int i=;i<;i++){
  33. for(int j=;j<;j++) res[i][j]=;
  34. }
  35. for(int i=;i<;i++) {
  36. for(int j=;j<;j++){
  37. temp[i][j]=Matrix[i][j];
  38. }//循环copy
  39. }
  40. for(int i=;i<;i++){//依照枚举数组将第一排按下
  41. if(A[i]==){
  42. res[][i]=;
  43. switch (i){
  44. case :
  45. Flip(temp[][i]);
  46. Flip(temp[][i+]);
  47. Flip(temp[][i]);
  48. break;
  49. case :
  50. Flip(temp[][i]);
  51. Flip(temp[][i-]);
  52. Flip(temp[][i]);
  53. break;
  54. default:
  55. Flip(temp[][i]);
  56. Flip(temp[][i-]);
  57. Flip(temp[][i+]);
  58. Flip(temp[][i]);
  59. break;
  60. }
  61. }
  62. }
  63. for(int i=;i<;i++){//其他数组依次往下按
  64. for(int j=;j<;j++){
  65. if(temp[i][j]==){
  66. res[i+][j]=;
  67. switch (j){
  68. case :
  69. Flip(temp[i][j]);
  70. Flip(temp[i+][j+]);
  71. Flip(temp[i+][j]);
  72. Flip(temp[i+][j]);
  73. break;
  74. case :
  75. Flip(temp[i][j]);
  76. Flip(temp[i+][j-]);
  77. Flip(temp[i+][j]);
  78. Flip(temp[i+][j]);
  79. break;
  80. default:
  81. Flip(temp[i][j]);
  82. Flip(temp[i+][j-]);
  83. Flip(temp[i+][j]);
  84. Flip(temp[i+][j+]);
  85. Flip(temp[i+][j]);
  86. break;
  87. }
  88. }
  89. }
  90. }
  91. for(int i=;i<;i++){
  92. if(temp[][i]==){
  93. res[][i]=;
  94. switch (i){
  95. case :
  96. Flip(temp[][i]);
  97. Flip(temp[][i+]);
  98. Flip(temp[][i]);
  99. break;
  100. case :
  101. Flip(temp[][i]);
  102. Flip(temp[][i-]);
  103. Flip(temp[][i]);
  104. break;
  105. default:
  106. Flip(temp[][i]);
  107. Flip(temp[][i-]);
  108. Flip(temp[][i+]);
  109. Flip(temp[][i]);
  110. break;
  111. }
  112. }
  113. }
  114. if(Check()){
  115. print(t);
  116. }
  117. }
  118. }
  119. }

不过这题可以利用二进制枚举法进行简化。

什么是二进制枚举法呢?

我在枚举从000000~111111的时候,我嵌套了6层循环,如果使用二进制来表示这个数组,我只需要枚举从0到31即可。

下面就是mooc老师写的代码。

  1. #include <memory>
  2. #include <string>
  3. #include <cstring>
  4. #include <iostream>
  5. using namespace std;
  6. int GetBit(char c,int i) {
  7. //取c的第i位
  8. return ( c >> i ) & ;
  9. }
  10. void SetBit(char & c,int i, int v) {
  11. //设置c的第i位为v
  12. if( v )
  13. c |= ( << i);
  14. else
  15. c &= ~( << i);
  16. }
  17. void Flip(char & c, int i) {
  18. //将c的第i位为取反
  19. c ^= ( << i);
  20. }
  21. void OutputResult(int t,char result[]) //输出结果
  22. {
  23. cout << "PUZZLE #" << t << endl;
  24. for( int i = ;i < ; ++i ) {
  25. for( int j = ; j < ; ++j ) {
  26. cout << GetBit(result[i],j);
  27. if( j < )
  28. cout << " ";
  29. }
  30. cout << endl;
  31. }
  32. }
  33. int main() {
  34. char oriLights[]; //最初灯矩阵,一个比特表示一盏灯
  35. char lights[]; //不停变化的灯矩阵
  36. char result[]; //结果开关矩阵
  37. char switchs; //某一行的开关状态
  38. int T;
  39. cin >> T;
  40. for( int t = ; t <= T; ++ t) {
  41. memset(oriLights,,sizeof(oriLights));
  42. for( int i = ;i < ; i ++ ) { //读入最初灯状态
  43. for( int j = ; j < ; j ++ ) {
  44. int s;
  45. cin >> s;
  46. SetBit(oriLights[i],j,s);
  47. }
  48. }
  49. for( int n = ; n < ; ++n ) { //遍历首行开关的64种状态
  50. memcpy(lights,oriLights,sizeof(oriLights));
  51. switchs = n; //第i行的开关状态
  52. for( int i = ;i < ; ++i ) {
  53. result[i] = switchs; //第i行的开关方案
  54. for( int j = ; j < ; ++j ) {
  55. if( GetBit(switchs,j)) {
  56. if( j > )
  57. Flip(lights[i],j-);//改左灯
  58. Flip(lights[i],j);//改开关位置的灯
  59. if( j < )
  60. Flip(lights[i],j+);//改右灯
  61. }
  62. }
  63. if( i < )
  64. lights[i+] ^= switchs;//改下一行的灯
  65. switchs = lights[i]; //第i+1行开关方案和第i行灯情况同
  66. }
  67. if( lights[] == ) {
  68. OutputResult(t,result);
  69. break;
  70. }
  71. } // for( int n = 0; n < 64; n ++ )
  72. }
  73. return ;
  74. }

PS:这手二进制枚举秀到我了。

总结:暴力破解也不是很轻松。需要使用者对破解边界有足够的熟练度才行。

(BruteForce)暴力破解经典题目总结的更多相关文章

  1. 一道关于压缩包的ctf题目(包括暴力破解,明文攻击,伪加密)

    关于题目附件 链接:https://pan.baidu.com/s/1PRshlizSndkgxkslnqJrHA 提取码:p76e zip三连击 下载附件得到题目 手机号码一般是11位,那么我们设置 ...

  2. 利用base64库暴力破解base加密

    做个base加密题python语法出了一堆错误..... 附上py中关于base加密/解码的知识:http://www.open-open.com/lib/view/open1433990719973 ...

  3. 《11招玩转网络安全》之第三招:Web暴力破解-Low级别

    Docker中启动LocalDVWA容器,准备DVWA环境.在浏览器地址栏输入http://127.0.0.1,中打开DVWA靶机.自动跳转到了http://127.0.0.1/login.php登录 ...

  4. Metasploit 暴力破解演示

    本文简要演示使用Metasploit 中的mysql_login.postgresql_login.tomcat_mgr_login模块暴力破解Metasploitable 2 上部署的服务. Pre ...

  5. Brute Force(暴力(破解))

    一.攻击模块1:Brute Force(暴力破解) 暴力破解一般指穷举法,穷举法的基本思想是根据题目的部分条件确定答案的大致范围,并在此范围内对所有可能的情况逐一验证,直到全部情况验证完毕.若某个情况 ...

  6. UVa 11059 最大乘积 java 暴力破解

    题目链接: https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_proble ...

  7. DVWA Brute Force:暴力破解篇

    DVWA Brute Force:暴力破解篇 前言 暴力破解是破解用户名密码的常用手段,主要是利用信息搜集得到有用信息来构造有针对性的弱口令字典,对网站进行爆破,以获取到用户的账号信息,有可能利用其权 ...

  8. burp暴力破解之md5和绕过验证码

    Burpsuite是一个功能强大的工具,也是一个比较复杂的工具 本节主要说明一下burp的intruder模块中的2个技巧 1.md5加密 我们在payload Processing中的add选项可以 ...

  9. 开源服务专题之------ssh防止暴力破解及fail2ban的使用方法

    15年出现的JAVA反序列化漏洞,另一个是redis配置不当导致机器入侵.只要redis是用root启动的并且未授权的话,就可以通过set方式直接写入一个authorized_keys到系统的/roo ...

随机推荐

  1. 安装go 1.5 & 部署

    https://storage.googleapis.com/golang/go1.5.linux-amd64.tar.gz tar -C /usr/local -xzf go1.5.linux-am ...

  2. ie9/8的iframe中jQuery报错

    此文章用于对工作中遇到的问题进行记录 jQuery 版本:1.9.1 按照一般的思路,jquery 1.x的是支持ie9及以下的,但是今天发现jquery报错了,代码错误位置在源码版本的第4888行 ...

  3. ORACLE 分区表 相关视图

    1. 显示当前用户可访问的所有分区表信息﹕ ALL_PART_TABLES 2. 显示当前用户所有分区表的信息﹕ USER_PART_TABLES 3. 显示表分区信息 显示数据库所有分区表的详细分区 ...

  4. jquery源码区块

  5. Leetcode 424.替换后的最长重复字符

    替换后的最长重复字符 给你一个仅由大写英文字母组成的字符串,你可以将任意位置上的字符替换成另外的字符,总共可最多替换 k 次.在执行上述操作后,找到包含重复字母的最长子串的长度. 注意:字符串长度 和 ...

  6. Vue样式绑定、事件绑定

    1.样式绑定 1.1class类标签绑定 <p :class="对象"> <p :class="数组"> <p :class=&q ...

  7. activemq的安装启动

    Activemq安装和启动   官网:http://activemq.apache.org/   安装启动: $ tar -zxvf apache-activemq-5.11.1-bin.tar.gz ...

  8. WTForms 表单动态验证

    class UserDetails(Form): group_id = SelectField(u'Group', coerce=int) def edit_user(request, id): us ...

  9. [UOJ#276]【清华集训2016】汽水

    [UOJ#276][清华集训2016]汽水 试题描述 牛牛来到了一个盛产汽水的国度旅行. 这个国度的地图上有 \(n\) 个城市,这些城市之间用 \(n−1\) 条道路连接,任意两个城市之间,都存在一 ...

  10. DB2 Catalog浅析&学习笔记

    原文地址:http://king123654789.iteye.com/blog/1296492 Catalog 是远程连接部署在服务器端的DB2数据库的命令 [本文涉及到的命令] >db2 c ...