世纪末的星期
答案:2299
代码如下:
public class Main{
public static void main(String[] args) {
//定义一个Calendar对象
Calendar calendar=Calendar.getInstance();
for (int year=1999;year<10000;year+=100){
//calendar.set()设置时间
calendar.set(Calendar.YEAR,year);
calendar.set(Calendar.MONTH,11);//12月 只有月份是0开始的,0对应1月
calendar.set(Calendar.DAY_OF_MONTH,31);//设置每月天数
if (calendar.get(Calendar.DAY_OF_WEEK)==1){//1代表周日
System.out.println(year);
break;
}
}
}
}
马虎的算式
答案:142
题中的变量就是a、b、c、d、e。依据题意我们可以设立五重循环得到五个不等的数字,再根据所给要求ab * cde = adb * ce进行判断。
代码如下:
public class Main{
public static void main(String[] args) {
int ans=0;
for (int a=1;a<10;a++){
for (int b=1;b<10;b++){
if (a!=b) for (int c=1;c<10;c++){
if (c!=a && c!=b)for (int d=1;d<10;d++){
if (d!=a && d!=b && d!=c)for (int e=1;e<10;e++){
if (e!=a && e!=b && e!=c && e!=d){
if ((a*10+b)*(c*100+d*10+e)==(a*100+d*10+b)*(c*10+e)){
ans++;
}
}
}
}
}
}
}
System.out.println(ans);
}
}
振兴中华
答案:35
其实,可以把最小方格看成一个个坐标,左上角的“从”为(0,0)。依据题意,要使跳过的路线刚好构成“从我做起振兴中华”这句话就不能后退,即只能向右和向下运动。
设i为行,j为列,绘制一个二叉树图,将向左方延申的定为(i+1),即向下运动的线路。向右方延申的定为(j+1),即向右运动的线路。
可以发现到最右侧的那条边或者最下方的边后就只有一种前进方向了所以可以将终止条件定为:
i==3 || j==4。
代码如下:
public class Main {
public static void main(String[] args) {
int ans=f(0,0);
System.out.println(ans);
}
private static int f(int i,int j){
if (i==3||j==4){
return 1;
}
return f(i+1,j)+f(i,j+1);//将两种走法的路线数相加
}
}
黄金连分数
答案:0.6180339887498948482045868343656381177203091798057628621354486227052604628189024497072072041893911375
其实在罗列几层后不难发现:1/(1+1/1)=1/2,1/(1+1/(1+1/1))=1/(1+1/2)...分母其实就是1+前面的结果。罗列一下为:1/2,2/3,3/5,5/8....分母符合斐波那契。且可以看为斐波那契相邻两项的比值。
所以我们需要注意:
将题目化为求斐波那契相邻两项的比值,项越多越精确,n/n+1项,n再往上增加,这个比值约小数点后101位是稳定的。
double无法表示100位小数,需要用到能够计算高精度的:BigInteger和BigDecimal
代码如下:
public class Main{
public static void main(String[] args){
BigInteger a=BigInteger.ONE;//基本常量1
BigInteger b=BigInteger.ONE;
for (int i=3;i<1000;i++){
//i<100或200、300时结果后面略有不同,为了得到高精度的结果可以把<号后面的数写大点
BigInteger t=b;
b=a.add(b);
a=t;
}
BigDecimal divide=new BigDecimal(a,110).divide(new BigDecimal(b,110),BigDecimal.ROUND_HALF_DOWN);
System.out.println(divide.toPlainString().substring(0,103));//其实102就够了,(小数点后100位,加上小数点及小数点前的0)
//但是还是写103保险,得到后101位,再手动四舍五入
}
}
有理数类
分数的相加:1/7+3/4 ==>(1*4)/(7*4)+(3*7)/(4*7) ==> (1*4+3*7)/(4*7)
答案:
class Rational
{
private long ra;//分子
private long rb;//分母
private long gcd(long a, long b){
if(b==0) return a;
return gcd(b,a%b);
}
public Rational(long a, long b){
ra = a;
rb = b;
long k = gcd(ra,rb);
if(k>1){ //需要约分
ra /= k;
rb /= k;
}
}
// 加法
public Rational add(Rational x){
return new Rational(this.ra*x.rb+x.ra*this.rb,this.rb*x.rb); //填空位置
}
// 乘法
public Rational mul(Rational x){
return new Rational(ra*x.ra, rb*x.rb);
}
public String toString(){
if(rb==1) return "" + ra;
return ra + "/" + rb;
}
}
三部排序
答案:
public class Main{
static void sort(int[] x){
int p = 0;
int left = 0;//下标
int right = x.length-1;//最大下标
while(p<=right){
if(x[p]<0){
//元素小于0,将元素和left位置交换
int t = x[left];
x[left] = x[p];
x[p] = t;
left++;
p++;
}
else if(x[p]>0){
//元素大于0,将元素和right位置交换
int t = x[right];
x[right] = x[p];
x[p] = t;
right--;
}
else{//元素等于0,不用交换位置
P++; //代码填空位置
}
}
}
}
错误票据
需要注意的是:从集合中取元素,取出的是对象。对象和对象之间作比较,如果要比较它们的内容是否相同,应该用到equals()
代码如下:
public class Main{
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
//本来数组要给定长度,但是此题我们不知道长度,所以需要动态的集合
ArrayList<Integer> list =new ArrayList<Integer>();
int N=sc.nextInt();
sc.nextLine();//吃掉整数后面的换行符
for (int i=0;i<N;i++){
String line=sc.nextLine();//输入的是一整行字符串
String[] split=line.split(" ");//用空格将该行的数据进行分割
for (int j=0;j<split.length;j++){
list.add(Integer.parseInt(split[j]));//把split的元素从Integer类型转换位int类型的
}
}
//对数组进行排序用Arrays,对集合进行排序用Collection
Collections.sort(list);
int m=0;
int n=0;
for (int i=1;i<list.size();i++){
if (list.get(i)-list.get(i-1)==2){
m=list.get(i)-1;
}
if (list.get(i).equals(list.get(i-1))){
n=list.get(i);
}
}
System.out.println(m+" "+n);
}
}
幸运数
依照题意,不论n多大,查找幸运数都需要先将2及2的倍数除掉,即起始数组内的元素只包含奇数 ==> arr[i]=2*i+1
又自3开始,除去的是被幸运数整除的序号位置的数。而此处所指的序号位置与数组下标不同,即数组下标+1能被幸运数整除的元素要删去。并让其后面的元素前移。
代码如下:
public class Main{
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
int m=sc.nextInt();
int n=sc.nextInt();
int[] a=new int[n];
for (int i=0;i<n;i++){
a[i]=2*i+1;
}
//已经把2的倍数给移除了
int l=1;//幸运数的下标,a[l]是幸运数
while (true){
int p=l+1;//数字向前移动的坑位
for (int i=l+1;i<n;i++){
if ((i+1)%a[l]==0){
}else{//i+1除幸运数a[l]除不尽的往前移
a[p]=a[i];
p++;
}
if (a[i]>n)break;
}
l++;
if (a[l]>=n)break;
}
int ans=0;
for (int i=0;i<n;i++){
if (a[i]>=n)break;
if (a[i]>m)ans++;
}
System.out.println(ans);
}
}
带分数
代码如下:
public class Main{
static int ans;
private static int N;
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
N=sc.nextInt();
int [] arr={1,2,3,4,5,6,7,8,9};
f(arr,0);
System.out.println(ans);
}
//确认某一个排列的第k位
private static void f(int[] arr,int k){
if (k==9) {
check(arr);
return;
}
//选定第k位,
for(int i=k;i<arr.length;i++){
//将第i位和第k位交换
int t=arr[i];
arr[i]=arr[k];
arr[k]=t;
// 移交下一层去确认k+1位
f(arr,k+1);
//回溯(换回来)
t=arr[i];
arr[i]=arr[k];
arr[k]=t;
}
}
/*枚举加号和除号的位置*/
private static void check(int[] arr){
//+前的字符数最多是?
for (int i=1;i<=7;i++){
int num1=toInt(arr,0,i);//+前面的一段整数
if (num1>=N)continue;//如果此时+号的数额已经超过了N,没必要验算
// /前面的字符数
for (int j=1;j<=8-i;j++){
int num2=toInt(arr,i,j);
int num3=toInt(arr,i+j,9-i-j);
if (num2%num3==0 && num1+num2/num3==N){
ans++;
}
}
}
}
private static int toInt(int[] arr,int pos,int len){
int t=1;
int ans=0;
for (int i=pos+len-1;i>=pos;i--){
ans+=arr[i]*t;
t*=10;
}
return ans;
}
private static void print(int[] arr){
for (int i=0;i<arr.length;i++){
System.out.println(arr[i]);
}
System.out.println();
}
}
连号区间数
代码如下:
public class Main{
public static void main(String[] args) {
Scanner sc =new Scanner(System.in);
int n=sc.nextInt();
int[] arr=new int[n+1];
for (int i=1;i<=n;i++){
arr[i]=sc.nextInt();
}
int ans=0;
for (int i=1;i<=n;i++){
int max=arr[i];
int min=arr[i];
for (int j=i;j<=n;j++){
if (arr[j]>max)max=arr[j];
if (arr[j]<min)min=arr[j];
if (i==j) {
ans++;
}else {
if (max-min==j-i){
ans++;
}
}
}
}
System.out.println(ans);
}
}