打表法与模拟法的使用及简单举例

本文介绍了如何使用模拟法和打表法解决蓝桥杯竞赛中的算式问题、求值、既约分数和天干地支等问题。通过具体的题目实例,展示了如何利用这两种方法寻找解决方案,提供了相应的代码示例和答案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

模拟法和打表法,经常会同时出现,因为打表就要按照题目的意思去模拟。

算式问题

 本题为填空题,只需要算出结果后,将结果填入即可。
 
看这个算式:
 
☆☆☆ + ☆☆☆ = ☆☆☆
 
如果每个五角星代表 1 ~ 9 的不同的数字。这个算式有多少种可能的正确填写方法?
 
173 + 286 = 459
295 + 173 = 468
173 + 295 = 468
183 + 492 = 675
 
以上都是正确的填写法!
 
注意:111+222=333 是错误的填写法!因为每个数字必须是不同的!也就是说:1 ~ 9 中的所有数字,每个必须出现且仅出现一次!
 
注意:不包括数字 “0”。
 
注意:满足加法交换率的式子算两种不同的答案。 所以答案肯定是个偶数!
 
运行限制:
 
 1. 最大运行时间:1s
 2. 最大运行内存: 128M

首先这道题只需要答案,那么对于时间要求就等于无限,可以使用模拟方法,因为只需要输出答案即可。

接下来采用模拟法进行问题的求解,注意既然不需要考虑时间问题和代码问题,一定要将代码设计的具有较高的逻辑性和准确性。

这个题的正解是搜索算法,但是既然只要答案,那就优先求快、求简单,在这里我们使用另一种方式进行解答。

这里有三个数字 A + B = C 且各个位上的数字不同。
我们这里借助桶排序的思想来判断 1-9 这些数字有没有占用。[用出现的数字表示数组的下标,出现了就计数为1,如果遍历时数组该下标对应值本就为1,说明该数字(下标)出现过]
所以我们定义一个判断函数,用于判断 A B C 三个数字是否符合要求。

然后暴力枚举:

  • A 从 123 到 987 开始枚举

 之所以不采用111-999不是因为不可以,而是因为 123 是最小的符合要求的数字,987 是最大的符合要求的数字,可以减少枚举的次数。

  • B 从 123 到 987-A 枚举

如果直接枚举与 A 不一样的数字那么又得考虑每一位的问题,这样的模拟已经不是暴力法了,我们要做的就是在不改变完成难度的情况下,减少复杂度。

  • C = A + B

这时候只要检查 A B C 是否符合要求即可。
代码解答:

import java.util.Map;
import java.util.Scanner;
import java.util.TreeMap;
 
public class Main {
 
    static int check(int a, int b, int c)
    {
        int flag[]=new int[11];
        for(int i=0;i<10;i++) flag[i]=0;
        flag[0]=1;//因为题目不允许出现数字0,所以先把下标为0处用数字1占掉
        while(a!=0)
        {
            if(flag[a%10]==1) return 0;//数字重复出现了
            else flag[a%10]=1;//之前没有这个数(下标),赋值
 
            if(flag[b%10]==1) return 0;
            else flag[b%10]=1  ;
 
 
            if(flag[c%10]==1) return 0;
            else flag[c%10]=1  ;
             //借助循环,依次把数字分开成单个的
            a=a/10;
            b=b/10;
            c=c/10;
 
        }
        return 1;
    }
 
    public static void main(String[] args) {
 
        int ans=0;
 
        for(int a=123;a<=987;a++)
            for(int b=123;b<=987-a;b++)
            {
                int c=a+b;
                if(check(a,b,c)==1)
                {
                    ans++;
                    System.out.println(a+"+"+b+"="+c);
                }
 
            }
        System.out.println(ans);
    }
}

 因为题目要求只提交答案,所以提交答案:336

求值

本题为填空题,只需要算出结果后,将结果填入即可。
 
学习了约数后,小明对于约数很好奇,他发现,给定一个正整数 t,总是可以找到含有 t 个约数的整数。小明对于含有 t 个约数的最小数非常感兴趣,并把它定义为 St​。
 
例如 S1=1,S2=2,S3=4,S4=6,⋅⋅⋅
 
现在小明想知道,当 t=100 时,S1​00 是多少?
 
运行限制:
 
 1. 最大运行时间:1s
 2. 最大运行内存:128M

这是一道数论题目,但是由于是道填空题,所以我们采用模拟法打表法做 。定义个找约束个数的函数,然后枚举即可。

代码如下:

package com.company;
 
public class Main {
 
  static int cnt(int a){
      int ans = 0;
      for (int j = 1; j <= a; j++)
          if (a % j == 0)
              ans++;
      return ans;
  }
 
  public static void main(String[] args) {
 
      for(int i=1;true;i++)
      {
 
          System.out.println(cnt(i)+" "+i);
          if(cnt(i)==100) break;
      }
  }
}

答案:45360

既约分数

本题为填空题,只需要算出结果后,将结果填入即可。
 
如果一个分数的分子和分母的最大公约数是 1,这个分数称为既约分数。
 
例如 3/4,1/8,7/1, 都是既约分数。
请问,有多少个既约分数,分子和分母都是 1 到 2020 之间的整数(包括 1 和 2020)?
运行限制
 1. 最大运行时间:1s
 2.最大运行内存:128M

有一个巧妙的方法是因为分子与分母是对称的我们可以少枚举一半。

这题目我们首先要两个数是否互质,即最大公约数为 1,我们就定义一个GCD() 求最小公约数的算法,这里我们采用的是递归的方法。

int gcd (int a,int b){
    return a%b ? gcd(b,a%b) : b;
}

然后这个题目我们就可以进行枚举了。

  • 外层循环为 a,假设是分母,内层循环是 b 这样就可以进行枚举
  • a 和 b 都是 1 到 2020

代码如下:

public class Main {
 
  static int gcd(int a, int b)
  {    
      return b==0 ? a : gcd(b,a%b) ;
      /*这样写太慢了
      int temp;
      while(b>0)
      {
          //利用辗除法,直到b为0为止
          temp = b;
          b = a % b;
          a = temp;
      }
      return a;
      */
  }
 
  public static void main(String[] args) {
      int ans=0;
      for(int a=1;a<=2020;a++)
      {
          for( int b=1;b<=2020;b++)
          {
              if(gcd(a,b)==1) ans++;
          }
 
      }
 
      System.out.println(ans);
  }
}

 答案:2481215

天干地支

古代中国使用天干地支来记录当前的年份。
 天干一共有十个,分别为:甲(jiǎ)、乙(yǐ)、丙(bǐng)、丁(dīng)、戊(wù)、己(jǐ)、庚(gēng)、辛(xīn)、壬(rén)、癸(guǐ)。
 地支一共有十二个,分别为:子(zǐ)、丑(chǒu)、寅(yín)、卯(mǎo)、辰(chén)、巳(sì)、午(wǔ)、未(wèi)、申(shēn)、酉(yǒu)、戌(xū)、 亥(hài)。

将天干和地支连起来,就组成了一个天干地支的年份,例如:甲子。
 
2020 年是庚子年。
每过一年,天干和地支都会移动到下一个。例如 2021 年是辛丑年。
 每过 60 年,天干会循环 6 轮,地支会循环 5 轮,所以天干地支纪年每 60 年轮回一次。例如 1900 年,1960 年,2020 年都是庚子年。
 
给定一个公元纪年的年份,请输出这一年的天干地支年份。
 
输入描述:
 输入一行包含一个正整数,表示公元年份。
 其中有 ,输入的公元年份为不超过 9999 的正整数。
 
输出描述:
 输入一行包含一个字符串,表示天干地支年份。
 
输入输出样例: 
输入

 2020

输出
 gengzi

运行限制
 1. 最大运行时间:1s
 2. 最大运行内存: 128M

种类比较多,天干有 10 种 ,地支有 12 种

现在我们知道了 2020 年是庚子年,这里既可以是除留余数来判断 N 年是什么天干和什么地支,我们也可以直接暴力使用循环做,这样的话 9999 的复杂度也跑不了多久。实现起来很简单,我们讲这个比较难的。

我们先判断 0000 年的天干 和地支 。

  • 根据题意 0000 年 距 2020 年 早了 2020 年 。
  • 已知天干 有 10 个, 那么 2020%10=0 剩下的都是整个轮回,即到了 0000 年 是庚 X 年,即天干是 庚 。

再按照这个方法算地支 是 2020%12=4 及还要向前推四年 地支为申。

即 0000年为庚申年,那么根据模拟法可知:

N%10=0 时 天干为庚

N%10=1 时 天干为辛...

以此类推

N%12=0 时 地支为申

N%12=1 时 地支为酉 ...

代码如下:

import java.util.Scanner;
 
public class Main {
 
    static String tg[] = new String []{"geng", "xin", "ren", "gui", "jia", "yi" , "bing", "ding", "wu", "ji"};
 
    static String dz[] = new String []{ "shen", "you", "xu", "hai", "zi", "chou", "yin", "mou", "chen", "si", "wu", "wei"};
 
    public static void main(String[] args)
    {
 
        int year;
        Scanner in =new Scanner(System.in);
        year = in.nextInt();
 
        System.out.println(tg[year%10]+""+dz[year%12]);
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值