C语言:5分钟内学会了暴力枚举法

举报
程序员飞鸟 发表于 2022/05/10 09:15:49 2022/05/10
【摘要】 在进行归纳推理时,如果逐个考察了某类事件的所有可能情况,因而得出一般结论,那么这结论是可靠的,这种归纳方法叫做枚举法

暴力枚举法

在进行归纳推理时,如果逐个考察了某类事件的所有可能情况,因而得出一般结论,那么这结论是可靠的,这种归纳方法叫做枚举法.


  • 枚举法,也叫暴力破解法,是一种基于逐个尝试答案的一种问题求解策略。

  • 最开始接触算法的时候,大家练习的基础算法都是有关于枚举算法的,比如打印出9 * 9的乘法表,求水仙花数,求素数等等,像这一类的题目就是在一定的范围内寻找满足条件的答案。

  • 枚举算法的核心思想就是:枚举所有的可能

目录

猜年龄

问题描述:

美国数学家维纳(N.Wiener)智力早熟,11岁就上了大学。他曾在1935~1936年应邀来中国清华大学讲学。 一次,他参加某个重要会议,年轻的脸孔引人注目。于是有人询问他的年龄,他回答说:“我年龄的立方 是个4位数。我年龄的4次方是个6位数。这10个数字正好包含了从0到9这10个数字,每个都恰好出现1次。”请你推算一下,他当时到底有多年轻。直接提交他那时的年龄数字

思路分析:

通过暴力破解的方法,找到年龄的大概范围,假设他的年龄为x,10^3=1000, 30^4=8100,说明x的范围在[10,30]之间。

 int main(){
     for(int i = 10;i <= 30;i++)
     {
         printf("%d= %.0f %.0f\n",i,pow(i,3),pow(i,4));//pow指i的立方,i的四次方
     }
     return 0;
 }

结果:

网友年龄

问题描述:

某君新认识一网友。当问及年龄时,他的网友说:“我的年龄是个2位数,我比儿子大27岁,

如果把我的年龄的两位数字交换位置,刚好就是我儿子的年龄”

请你计算:网友的年龄一共有多少种可能情况?

提示:30岁就是其中一种可能哦.

请填写表示可能情况的种数。

思路分析:

网友的年龄比他儿子大27,就说明网友至少27岁,即为初始值为27,两位数最大也就是99,范围【27,99】,假设网友年龄为i,设个位为b,十位数为10a,把他的年龄数字交换位置正好是他的儿子的年龄,那么他儿子的年龄为10b+a,判断条件是网友的年龄减去27等于他儿子的年龄,sum累加几种可能性。

 #include<stdio.h>
 #include<math.h>
 int main()
 {
     int i,a,b,son,sum=0;
 ​
     for(i=27;i<100;i++){
         a=i/10;
         b=i%10; //例如41对10整除取4,对10取余得1,即他儿子14岁
         son=(b*10)+a;
         
         if(27==i-son){
             printf("%d\n",i);
             sum++;
         }
         
     }
     printf("共有%d种可能性\n",sum);
     return 0;
 }

结果:

 30
 41
 52
 63
 74
 85
 96
 共有7种可能性

生日年龄数

问题描述:

某君从某年开始每年都举办一次生日party,并且每次都要吹熄与年龄相同根数的蜡烛。现在算起来,他一共吹熄了236根蜡烛。

请问,他从多少岁开始过生日party的?

请输出他开始过生日party的年龄数。

注意:你输出的应该是一个整数,不要输出任何多余的内容或说明性文字。

输入

没有输入。

输出

输出一个整数,即某君开始过生日party的年龄数

提示

用printf或cout输出答案。

思路分析:

假设i为初始年龄,j为终止年龄,j肯定要大于i,那么j=i+1,k为多少根蜡烛!暴力累加。

 int main()
 {
 ​
     for(int i=1;i<=100;i++)
     {
         for(int j=i+1;j<=100;j++)
         {
             int sum=0; 
             for(int k=i;k<=j;k++){
                 sum += k;
             
             }
             if(sum==236)
                printf("%d",i);
         }
     }
     return 0;
 }

结果:26

数学题

问题描述:

有限五位数

个位数为6且能被3整除的五位数有多少个?

思路分析:

首先分析5位数的范围【10000,99999】,个位数为6说明至少两位数,并对3取余,ans累加。

 #include <stdio.h>
 #include <stdlib.h>
 ​
 int main() {
     int ans=0;
     for(int i=10000;i<=99999;i++){
         if((i*10+6)%3==0){
             ans++;
         }
     }
     printf("能被3整除的有%d个",ans);
      
     return 0;
 }

结果:能被3整除的有3000个

马虎的算式

问题描述:

小明是个急性子,上小学的时候经常把老师写在黑板上的题目抄错了。有一次,老师出的题目是:36 x 495 =? 他却给抄成了:396 x 45 = ? 但结果却很戏剧性,他的答案竟然是对的!! 因为 36 * 495 = 396 * 45= 1782 类似这样的巧合情况可能还有很多,比如:27* 594 = 297 * 54

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

能满足形如: ab * cde = adb* ce 这样的算式一共有多少种呢?请你利用计算机的优势寻找所有的可能,并回答不同算式的种类数。

满足乘法交换律的算式计为不同的种类,所以答案肯定是个偶数。

答案直接通过浏览器提交。注意:只提交一个表示最终统计种类数的数字,不要提交解答过程或其它多余的内容。

思路分析:

假设a b c d e 代表1~9不同的5个数字,a b c d e的范围在【1,9】,有多少种结果用ans累加法,通过判断条件abcde=adbce满足条件累加1,然后有一种可能就是a与b相等,所以判断否定a不等于b,其他字母也一样。

  #include<stdio.h>
  int main(){
     int ans=0,m,n;
     for(int a = 1;a<=9;a++){
         for(int b = 1;b<=9;b++){
             for(int c = 1;c<=9;c++){
                 for(int d =1;d<=9;d++){
                     for(int e =1;e<=9;e++){
                         
                         m = (a*10+b)*(c*100+d*10+e);
                         n = (a*100+d*10+b)*(c*10+e);
                         if(m==n&&a!=b&&a!=c&&a!=d&&a!=e&&b!=c&&b!=d&&b!=e&&c!=d&&c!=e&&d!=e){
                             ans++;
                         }
                     }
                 }
             }
         }
     }
     printf("一共%d种",ans);
     return 0;
  }

结果:142

奇怪的分式

问题描述:

上小学的时候,小明经常自己发明新算法。一次,老师出的题目是: 1/4 乘以 8/5 小明居然把分子拼接在一起,分母拼接在一起,答案是:18/45。老师刚想批评他,转念一想,这个答案凑巧也对啊,真是见鬼!

对于分子、分母都是 1~9 中的一位数的情况,还有哪些算式可以这样计算呢? 请写出所有不同算式的个数(包括题中举例的)。

显然,交换分子分母后,例如:4/1 乘以 5/8 是满足要求的,这算做不同的算式。

但对于分子分母相同的情况,2/2 乘以 3/3 这样的类型太多了,不在计数之列!

注意:答案是个整数(考虑对称性,肯定是偶数)。

请通过浏览器提交。不要书写多余的内容。

思路分析:

其实跟上一道差不多,找出范围,找出判断条件,找出不符合条件,利用累加ans

注意不可以用(a/b)*(c/d)==((a*10+c)/b*10+d)),而是利用数学里面的十字相乘法

  #include<stdio.h>
  int main(){
     int ans=0;
     for(int a=1;a<=9;a++){
         for(int b =1;b<=9;b++){
             for(int c =1;c<=9;c++){
                 for(int d=1;d<=9;d++){
                     if(a==b&&c==d)
                         continue;
                     int e = a*10+c,f = b*10+d;
                     if(a*c*f==b*d*e){
                         ans++;
                     }   
                     
                 }
             }
         }
     }
     printf("%d",ans);
     return 0;
  }

结果:14

几何题

问题描述:

小蓝有一个超大的仓库,可以摆放很多货物。现在,小蓝有 n 箱货物要摆放在仓库,每箱货物都是规则的正方体。小蓝规定了长、宽、高三个互相垂直的方向,每箱货物的边都必须严格平行于长、宽、高。小蓝希望所有的货物最终摆成一个大的立方体。即在长、宽、高的方向上分别堆 L 、 W 、 H 的货物,满足 n = L × W × H。给定 n ,请问有多少种堆放货物的方案满足要求。

例如,当 n = 4 时,有以下 6 种方案: 1 × 1 × 4 、 1 × 2 × 2 、 1 × 4 × 1 、 2 × 1 × 2 、 2 × 2 × 1 、 4 × 1 × 1

请问,当 n = 2021041820210418 (注意有 16位数字)时,总共有多少种方案? 提示:建议使用计算机编程解决问题。

思路分析:

循环暴力枚举解决法,理论上可以,可行性不行,转换思路分解出整个数字的所有因(约)数,然后对所有的因数暴力枚举两重循环,计算出结果。

  #include<stdio.h>
  int judge(long long a,long long b,long long c)
  {
     if(a==b==c)//长宽高相同排列只有一种组合
       return 1;
      if(a==b&&a!=c||a==c&&a!=b||b==c&&a!=b) //长宽高 任意两个相同排列只有3种
       return 3;
      else
        return 6; //长宽高都不相同排列只有6种
     
        
  }
  int mian()
  {
     long long n =2021041820210418;
     long long L,W,H;
     long long ans=0;
     
     for(L=1;L*L*L<=n;L++) //l是最小的一方
      {
         if(n%L==0)//小优化
       {
             
          
          for(W=L;L*W*W<=n;W++)//l是第二大的一方,次数多
          {
             if(n%(L*W)==0)//小优化 
             {
                 H=n/L/W;
                  if(H>=W){
                     ans+=judge(L,W,H);
                  } 
             }
          }
   }
         
       
      
     }
      printf("%d",ans);
     
     
       
  } 
 ​

结果:2430

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。