- 问题 1095: The 3n + 1 problem
考虑下面的算法生成一个数字序列。先从一个整数n。如果n是偶数,除以2,如果n是奇数,乘以3,并添加1。重复此过程,直到n = 1。例如,将对于n生成数的下列序列
n= 22:22 11 34 17 52 26 13 40 20 10 5 16 8 4 2 1据推测(但尚未证实),该算法将对于每个整数n在n = 1终止。另外,在上述的例子中,22中的周期长度是16.给出任意两个数字i和j,确定i和j之间在所有数字的最大周期长度(包括两个端点)。
import java.util.Scanner;
//输入未说明大小顺序,因此需要先排序,否则错误33
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
while (sc.hasNext()) {
int start,end;
int maxcount = 0;
int a = sc.nextInt();
int b= sc.nextInt();
if(a>b) {
end=a;
start=b;
}else {
start=a;
end=b;
}
for (int i = start; i <= end; i++) {
int count = 1;
int j = i;
while (j != 1) {
if (j % 2 == 0) {
j /= 2;
count++;
} else {
j = j * 3 + 1;
count++;
}
}
if (count > maxcount)
maxcount = count;
}
System.out.println(a + " " + b + " " + maxcount);
}
sc.close();
}
}
- 问题 1097: 蛇行矩阵
易得出,最大数为1~n求和,从右上角依次向左下角递减,构造一个数组存放,注意输出格式
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
int[][] num;
Scanner sc = new Scanner(System.in);
while (sc.hasNext()) {
int n = sc.nextInt();
int N = (n * n + n) / 2;
num = new int[n][n];
while (N > 0) {
for (int i = n - 1; i >= 0; i--) {
int x = 0;
for (int y = i; y >= 0; y--, x++) {
num[x][y] = N--;
}
}
}
for (int i = 0; i < n; i++) {
int m=n-i;
for (int j = 0; j < m; j++) {
if(j==m-1)
System.out.print(num[i][j]);
else
System.out.print(num[i][j]+" ");
}
System.out.println();
}
}
sc.close();
}
}
不使用数组的思路,行从0开始,列从1开始,则可推出
每行首位置数值=上一行首位置数值+本行行数(首行首位初始化为1)
每行非首位置数值=前一列数值+本行行数+本列列数
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
while (sc.hasNext()) {
int daty = 1, datx = 1;
int n = sc.nextInt();
int m = n;
for (int x = 0; x < n; x++) {
for (int y = 1; y <= m; y++) {
if (y == 1) {
if (x != 0)
daty += x;
System.out.print(daty + " ");
datx = daty;
}
else {
datx += x + y;
if (y == m)
System.out.print(datx);
else
System.out.print(datx + " ");
}
}
System.out.println();
m--;
}
}
sc.close();
}
}
这个题困扰了我一天,查到的答案都很简略,果然是我太菜了==
题干说的很复杂,根据例子自己写一写应该可以理解,直接说做法
w/k即为完整的段数,若正好可以完整分段,则相当于从可表达的7个状态(1——2^k-1,因为必须从左向右递增,且最少两段,所以不取0)中选出i【2<=i<=w/k】个状态放置,即求组合数(取出不放回,不求顺序)C(7,i)【2<=i<=w/k】。
若w/k有余数,则最高位可表达的就是1——2^(w%k)个状态,若直接求最高位有值的可取数,以w=3,k=8而言,相当于最高位从1——3中取1,其余两位从2——7 6个状态中取两个+最高位取2,其余从3——7 5个状态取两个+……,计算相对复杂。所以采用减法思维,用最高位从1——7任选(这种情况就是C(7,3))减去最高位从不能用的状态4——7中任选(这种情况就是C(4,3))。
这里给出组合数的计算公式,代码中使用时将n!与(n-m)!约了一下
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
while (scanner.hasNext()) {
int k = scanner.nextInt();
int w = scanner.nextInt();
int h = w % k;// 多余的位数作为最高位
int n = w / k + 1;// 此数值有多少位
int max = (int) Math.pow(2, k) ;
int high = (int) (Math.pow(2, h) - 1);
long count = 0;
if (k > 9 || k < 0)
break;
else {
for (int i = 2; i < n; i++)
count += c(max, i);
if (high != 0) {
count += (c(max, n) - c(max - high, n));
}
System.out.println(count);
}
}
}
public static long c(int max, int pos) {
int count=1;
for(int i=1;i<=pos;i++) {
count*=(max-i);
}
for(int i=2;i<=pos;i++) {
count/=i;
}
return count;
}
}