文章目录
- [A 隔行变色](#A 隔行变色)
- [B 立方尾不变](#B 立方尾不变)
- [C 无穷分数](#C 无穷分数)
- [D 奇妙的数字](#D 奇妙的数字)
- [E 移动距离](#E 移动距离)
- [F 垒骰子](#F 垒骰子)
A 隔行变色
思路
这是一个简单的计数问题。我们需要找出21到50之间的奇数数量。奇数行将被染成蓝色,偶数行将被染成白色。
解题方法
我们可以使用一个for循环从21遍历到50,然后使用模运算符(%)来检查每个数字是否为奇数。如果数字是奇数(即,如果数字除以2的余数为1),我们就增加计数器。
复杂度
时间复杂度:
O ( n ) O(n) O(n),其中n是我们需要检查的数字范围的大小。在这种情况下,n是30 ( 50 − 21 + 1 ) (50-21+1) (50−21+1)。
空间复杂度:
O ( 1 ) O(1) O(1),我们只需要一个变量来存储计数。
Code
java
public class Main {
public static void main(String[] args) {
// 奇数 蓝色
// 偶数 白色
int res = 0;
for(int i = 21; i <= 50; i++) {
if(i % 2 == 1) {
res++;
}
}
System.out.println(res);
}
}
B 立方尾不变
思路
这个问题是要找出1到10000之间的所有数字,这些数字的立方的尾部数字与原数字相同。例如,如果数字是12,它的立方是1728,尾部两位数字是12,与原数字相同。
解题方法
我们可以使用一个for循环从1遍历到10000,然后计算每个数字的立方。然后,我们将立方和原数字都转换为字符串,比较立方的尾部数字是否与原数字相同。
复杂度
时间复杂度:
O ( n ) O(n) O(n),其中n是我们需要检查的数字范围的大小。在这种情况下,n是10000。
空间复杂度:
O ( 1 ) O(1) O(1),我们只需要几个变量来存储计数和临时结果。
Code
java
public class Main {
static int MAXN = (int) 1e4;
public static void main(String[] args) {
int res = 0;
for (int i = 1; i <= MAXN; i++) {
if (deal(i)) {
res++;
}
}
System.out.println(res);
}
private static boolean deal(int x) {
// TODO Auto-generated method stub
long num = (long) x * x * x;
String s = num + "";
String t = x + "";
int len = t.length();
return s.substring(s.length() - len).equals(t);
}
}
C 无穷分数
思路
这个问题是要计算一个无穷分数序列的值。这个序列的形式是 1 + 2 / ( 3 + 4 / ( 5 + 6 / ( 7 + . . . ) ) ) 1 + 2/(3 + 4/(5 + 6/(7 + ...))) 1+2/(3+4/(5+6/(7+...)))。我们可以从最内层的分数开始,逐步向外计算。
解题方法
我们可以使用一个for循环从10000逆序遍历到1。对于每个i,我们计算(i - 1) + (i / res),其中res是前一步的结果。最初的res是98.0 + 99.0 / 100.0,对应于序列的最内层的分数。
复杂度
时间复杂度:
O ( n ) O(n) O(n),其中n是我们需要计算的分数的数量。在这种情况下,n是10000。
空间复杂度:
O ( 1 ) O(1) O(1),我们只需要一个变量来存储计算结果。
Code
java
public class Main {
public static void main(String[] args) {
double res = 98.0 + 99.0 / 100.0;
for(double i = 10000; i >= 1; i--) {
res = (i - 1) + (i / res);
}
System.out.printf("%.5f",res);
}
}
D 奇妙的数字
思路
这个问题是要找出1到1000之间的第一个数字,这个数字的平方和立方的每一位数字都是唯一的,并且0到9的每个数字都在这个数字的平方或立方中至少出现一次。
解题方法
我们可以使用一个for循环从1遍历到1000,然后计算每个数字的平方和立方。然后,我们将平方和立方都转换为字符串,检查每一位数字是否唯一,并且0到9的每个数字都至少出现一次。
复杂度
时间复杂度:
O ( n ) O(n) O(n),其中n是我们需要检查的数字范围的大小。在这种情况下,n是1000。
空间复杂度:
O ( 1 ) O(1) O(1),我们只需要一个布尔数组来存储每个数字是否出现过。
Code
java
public class Main {
static int MAXN = (int) 1e3;
public static void main(String[] args) {
for (int i = 1; i <= MAXN; i++) {
if (deal(i)) {
System.out.println(i);
break;
}
}
}
private static boolean deal(int x) {
// TODO Auto-generated method stub
String p2 = (x * x) + "";
String p3 = (x * x * x) + "";
boolean[] vis = new boolean[10];
for (int i = 0; i < p2.length(); i++) {
if (vis[p2.charAt(i) - '0']) {
return false;
} else {
vis[p2.charAt(i) - '0'] = true;
}
}
for (int i = 0; i < p3.length(); i++) {
if (vis[p3.charAt(i) - '0']) {
return false;
} else {
vis[p3.charAt(i) - '0'] = true;
}
}
for(int i = 0; i <= 9; i++) {
if(vis[i] == false) {
return false;
}
}
return true;
}
}
E 移动距离
思路
这是一个二维平面上的移动问题。我们需要找到从点m到点n的最短距离。这个问题的关键在于,我们的移动是在一个特殊的格子系统中进行的,其中每一行的移动方向可能会改变。因此,我们需要分别计算在行和列上的移动距离。
解题方法
我们首先计算出点m和点n在哪一行,然后根据行数的奇偶性确定它们在该行的位置。如果行数是奇数,那么位置就是m或n除以宽度w的余数;如果行数是偶数,那么位置就是宽度w减去m或n除以宽度w的余数再加1。最后,我们计算出行和列上的距离,然后将它们相加,得到总的移动距离。
复杂度
时间复杂度:
O ( 1 ) O(1) O(1)。我们只进行了一些基本的数学运算,所以时间复杂度是常数。
空间复杂度:
O ( 1 ) O(1) O(1)。我们只使用了一些基本的变量,所以空间复杂度也是常数。
Code
java
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.StreamTokenizer;
public class Main {
static BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
static PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));
static StreamTokenizer sr = new StreamTokenizer(in);
static int w, m, n;
public static void main(String[] args) throws IOException {
w = nextInt();
m = nextInt();
n = nextInt();
int a = (m + w - 1) / w, b = 0, c = (n + w - 1) / w, d = 0;
if(((m + w - 1) / w) % 2 == 1) {
// 奇数行
b = m % w;
} else {
// 偶数行
b = (w - m % w) + 1;
}
if(((n + w - 1) / w) % 2 == 1) {
// 奇数行
d = n % w;
} else {
// 偶数行
d = (w - n % w) + 1;
}
out.println(Math.abs(c - a) + Math.abs(d - b));
out.flush();
}
static int nextInt() throws IOException {
sr.nextToken();
return (int) sr.nval;
}
}
F 垒骰子
思路
这是一个动态规划问题,我们需要计算在给定的限制下,可以有多少种方式来堆叠骰子。我们可以使用一个矩阵来表示骰子的六个面,然后使用动态规划的方法来计算每一种可能的堆叠方式。
解题方法
我们首先初始化一个6x6的矩阵,然后根据输入的限制来更新这个矩阵。然后我们使用动态规划的方法来计算每一种可能的堆叠方式。我们使用一个循环来遍历所有的骰子,然后在每一次循环中,我们都会更新我们的动态规划矩阵。最后,我们将动态规划矩阵中的所有元素相加,得到最终的结果。
复杂度
时间复杂度:
O ( n 3 ) O(n^3) O(n3)。我们需要遍历所有的骰子,并且在每一次循环中,我们都需要更新我们的动态规划矩阵。
空间复杂度:
O ( n 2 ) O(n^2) O(n2)。我们需要一个6x6的矩阵来存储动态规划的结果。
Code
java
import java.io.*;
import java.util.Arrays;
public class Main {
static BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
static PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));
static int N = 6, mod = (int)1e9 + 7, n, m;
static long[][] A = new long[N][N];
static long[][] f = new long[N][N];
static int[] op = {3, 4, 5, 0, 1, 2};
public static void mul(long[][] a, long[][] b, long[][] c) {
long[][] t = new long[N][N];
for (int i = 0; i < N; i ++)
for (int j = 0; j < N; j ++)
for (int k = 0; k < N; k ++)
t[i][j] = (t[i][j] + b[i][k] * c[k][j]) % mod;
System.arraycopy(t, 0, a, 0, N);
}
public static void main(String[] args) throws IOException {
String[] s1 = in.readLine().split(" ");
n = Integer.parseInt(s1[0]); m = Integer.parseInt(s1[1]);
for (int i = 0; i < N; i ++) Arrays.fill(A[i], 4);
while (m -- > 0) {
String[] s2 = in.readLine().split(" ");
int x = Integer.parseInt(s2[0]) - 1, y = Integer.parseInt(s2[1]) - 1;
A[x][op[y]] = 0;
A[y][op[x]] = 0;
}
Arrays.fill(f[0], 4);
for (int k = n - 1; k > 0; k >>= 1) {
if ((k & 1) == 1) mul(f, f, A);
mul(A, A, A);
}
long res = 0;
for (int i = 0; i < N; i ++) res = (res + f[0][i]) % mod;
out.println(res);
out.flush();
}
}