题目链接
A.6的个数
签到题,遍历一遍即可
public class Main {
public static void main(String[] args) {
int ans = 0;
for(int i=1;i<=2016;i++) {
int temp=i;
while(temp!=0) {
if(temp%10==6)ans++;
temp/=10;
}
}
System.out.println(ans);
}
}
B.小明的作业
实不相瞒,我是用word文档查出来的,除了
a
和w
,其他字母用*
代替,然后查,然后千万不要有小可爱沾沾自喜的然后看错题意直接输出和了。。。
C.斐波那契
用了一个公约数,需要注意的是要用long,不然会爆int。还有就是每次进行运算的时候都需要除一次公约数,不然long也会爆。
import java.math.BigInteger;
public class Main {
public static long gcd(long m,long n) {
if(n==0)return m;
else return gcd(n,m%n);
}
public static void main(String[] args) {
long arr[] = new long[14];
arr[0] = 1;
arr[1] = 1;
for(int i=2;i<14;i++) {
arr[i] = arr[i-1]+arr[i-2];
}
long fz = 1;
long fm = 1;
for(int i=1;i<13;i++) {
fz = fz*arr[i]*arr[i+1]+fm;
fm = fm*arr[i]*arr[i+1];
long t =gcd(fz,fm);
fz=fz/t;
fm=fm/t;
}
System.out.println(fz+"/"+fm);
}
}
D.数组重现
这个是一个全排列,之前比较迷的地方是判断升序降序段,当时没有想到数学的知识:没有极值点说明有一个单调段,有一个极值点说明有两个单调段,有两个极值点说明有三个单调段。很明显,这道题使极值点的数目<3即可。
import java.util.HashSet;
public class Main {
public static int a[] = {2,5,3,6,3,6,7,3,7,8};
public static HashSet<String>hs = new HashSet<>();
public static void qpl(int k) {
if(k>=a.length) {
String str = "";
for (int i = 0; i < a.length; i++) {
str+=a[i];
}
StringBuilder sb = new StringBuilder();
sb.append(""+a[0]);
int bool = 0;//记录升序或者降序,1升-1降0平
int x = 0;//记录极值点个数
for(int i=1;i<a.length;i++) {
sb.append(""+a[i]);
if(a[i]>a[i-1]) {
if(bool==-1) {
x++;
//如果之前是降序且a[i]>a[i-1],说明有一个极值点
bool=0;
//操作完成之后将bool还原为初始值
}else bool = 1;
//如果之前不是降序,则说明没有极值点,将bool赋值为升序
}
//下边的操作和上边一样
if(a[i]<a[i-1]) {
if(bool==1) {
x++;
bool=0;
}else bool = -1;
}
}
//如果极值点<3则说明不超过3个单调的段,符合题意
if(x<3)hs.add(sb.toString());
}else {
for(int i=k;i<a.length;i++) {
int t = a[i];a[i]=a[k];a[k]=t;
qpl(k+1);
t = a[i];a[i]=a[k];a[k]=t;
}
}
}
public static void main(String[] args) {
qpl(0);
System.out.println(hs.size());
//System.out.println(21456);
}
}
F.字符串
这个要看清题意啊!!题目说了只有连续的
@wyk
才是有效的,所以判断有没有这个字符串就行了
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
sc.nextLine();
int ans = 0;
while(n-->0) {
String s = sc.nextLine();
if(s.contains("@wyk"))ans++;
}
System.out.println(ans);
}
}
G.最强对手矩阵
这个题首先可以看出来是一个前缀和,但是二维前缀和太麻烦了,可以采用一维前缀和将每一列元素进行前缀和,然后找一个上界,找一个下界,依次遍历得出连续子序列的最大和。 类似的题有(一维的最大连续子数组的和
)和(二维的最大连续子数组的和)
import java.util.Scanner;
public class Main {
//二维前缀和求最大值
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int m = sc.nextInt();
int a[][] = new int[n+1][m+1];
for(int i=1;i<=n;i++) {
for(int j=1;j<=m;j++) {
a[i][j] = sc.nextInt();
}
}
int ans = Integer.MIN_VALUE;
if(n<m) {//时间复杂度为n^2 * m
for(int i=1;i<=n;i++) {
for(int j=1;j<=m;j++) {
a[i][j]+=a[i-1][j];//a数组赋值
}
}
for(int i=1;i<=n;i++) {//上界
for(int j=i;j<=n;j++) {//下界
int s = 0;
for(int k=1;k<=m;k++) {//列标
if(s<=0)s=a[j][k]-a[i-1][k];
else s+=a[j][k]-a[i-1][k];
ans = Math.max(s,ans);
}
}
}
}else {//n>m时间复杂度为m^2*n
int b[][] = new int[m+1][n+1];
for(int i=1;i<=m;i++) {
for(int j=1;j<=n;j++) {
b[i][j]=a[j][i];//矩阵翻转
}
}
for(int i=1;i<=m;i++) {
for(int j=1;j<=n;j++) {
b[i][j]+=b[i-1][j];
}
}
for(int i=1;i<=m;i++) {//上界
for(int j=i;j<=m;j++) {//下界
int s = 0;
for(int k=1;k<=n;k++) {//列标
if(s<=0)s=b[j][k]-b[i-1][k];
else s+=b[j][k]-b[i-1][k];
ans = Math.max(s,ans);
}
}
}
}
System.out.println(ans);
}
}