模拟法和打表法,经常会同时出现,因为打表就要按照题目的意思去模拟。
算式问题
本题为填空题,只需要算出结果后,将结果填入即可。
看这个算式:
☆☆☆ + ☆☆☆ = ☆☆☆
如果每个五角星代表 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 时,S100 是多少?
运行限制:
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]);
}
}