目录
B题-数位dp
思路:写个方法判断一下就可以了,满足要求的就累加个数。AC代码如下:
public class Main {
public static void main(String[] args) {
int ans = 0 ;
for(int i=13930; i<=457439; i++){
if(dp(i)){
ans ++ ;
}
}
System.out.println(ans);
}
private static boolean dp(int x){
String s = String.valueOf(x) ;
int first = s.charAt(0) - '0' ;
int last = s.charAt(s.length()-1) - '0' ;
if(Math.abs(first-last)<=2){
return false ;
}
for(int i=1; i<s.length(); i++){
int m = s.charAt(i-1) - '0' ;
int n = s.charAt(i) - '0' ;
if(Math.abs(m-n)>7){
return false ;
}
}
return true ;
}
}
D题-兰德索尔杯-cup
思路:细心一点模拟整个过程就可以,注意细节,我起初一直AC不了,竟然把四个数字换行打印了,无语,人家明明放在一行好吧,我这是咋啦,不说了,AC代码奉上。
import java.util.Scanner;
public class Main {
static int n ;
static String [] s ;
public static void main(String[] args) {
Scanner input = new Scanner(System.in) ;
n = input.nextInt() ;
s = new String [4] ;
for(int i=0; i<4; i++){
s[i] = input.next() ;
}
double acc , ans ;
for(int j=0; j<4; j++) {
ans = acc= 0 ;
for (int i = 0; i < s[j].length(); i++) {
if(s[j].charAt(i)=='>'){
ans += 0.5 ;
acc = 4.5 ;
continue;
}
if(s[j].charAt(i)=='.' && acc >0){
if(acc>=0.5) {
ans += 0.5;
acc -= 0.5;
}else{
ans += acc + (1- acc*2) ;
acc = 0 ;
}
continue;
}
if(s[j].charAt(i)=='.' && acc <= 0){
ans += 1 ;
continue;
}
if(s[j].charAt(i)=='w' && acc >0){
if(acc>=1) {
ans += 1;
acc--;
}else{
ans += acc + (1-acc)*2 ;
acc = 0 ;
}
continue;
}
if(s[j].charAt(i)=='w' && acc <=0){
ans += 2 ;
continue;
}
if(s[j].charAt(i)=='s'){
ans ++ ;
acc-- ;
if(acc>0){
if(acc>=0.5) {
ans += 0.5;
acc -= 0.5;
}else{
ans += acc + (1- acc*2) ;
acc = 0 ;
}
}else{
ans += 1 ;
}
}
if(s[j].charAt(i)=='m'){
ans += 2 ;
acc -= 2 ;
if(acc>0){
if(acc>=0.5) {
ans += 0.5;
acc -= 0.5;
}else{
ans += acc + (1- acc*2) ;
acc = 0 ;
}
}else{
ans += 1 ;
}
}
}
System.out.printf("%.1f ",ans);
}
}
}
当然了,这样写,也是可以的,一样的思路。
import java.util.Scanner;
public class Main {
static int n ;
static String [] s ;
public static void main(String[] args) {
Scanner input = new Scanner(System.in) ;
n = input.nextInt() ;
s = new String [4] ;
for(int i=0; i<4; i++){
s[i] = input.next() ;
}
double acc , ans ;
for(int j=0; j<4; j++) {
ans = acc= 0 ;
for (int i = 0; i < s[j].length(); i++) {
if(s[j].charAt(i)=='>'){
ans += 0.5 ;
acc = 4.5 ;
continue;
}
if(s[j].charAt(i)=='.' && acc >0){
if(acc>=0.5) {
ans += 0.5;
acc -= 0.5;
}else{
ans += acc + (1- acc*2) ;
acc = 0 ;
}
continue;
}
if(s[j].charAt(i)=='.' && acc <= 0){
ans += 1 ;
continue;
}
if(s[j].charAt(i)=='w' && acc >0){
if(acc>=1) {
ans += 1;
acc--;
}else{
ans += acc + (1-acc)*2 ;
acc = 0 ;
}
continue;
}
if(s[j].charAt(i)=='w' && acc <=0){
ans += 2 ;
continue;
}
if(s[j].charAt(i)=='s'){
ans ++ ;
acc-- ;
if(acc>0){
if(acc>=0.5) {
ans += 0.5;
acc -= 0.5;
}else{
ans += acc + (1- acc*2) ;
acc = 0 ;
}
}else{
ans += 1 ;
}
}
if(s[j].charAt(i)=='m'){
ans += 2 ;
acc -= 2 ;
if(acc>0){
if(acc>=0.5) {
ans += 0.5;
acc -= 0.5;
}else{
ans += acc + (1- acc*2) ;
acc = 0 ;
}
}else{
ans += 1 ;
}
}
}
System.out.printf("%.1f ",ans);
}
}
}
F题-大数据分析
思路:签到题,注意是求总和,不是求第30天。
public class Main {
static int mod = 1000000007 ;
public static void main(String[] args) {
long ans = 1, sum = 1 ;
for(int i=2; i<=30; i++){
ans = ans * (ans + 5) % mod ;
sum = (sum + ans) % mod ;
}
System.out.println(sum);
}
}
G题-数学math
思路;这题乍一看简单,仔细一看,发现数据太大了,正常的写法AC不了,爆内存了。我的爆的代码仅供参考。
import java.util.Scanner;
public class Main {
static int mod = 1000000007 ;
static int k, a, b ;
static int l, r ;
static long [][] c ;
public static void main(String[] args) {
Scanner input = new Scanner(System.in) ;
k = input.nextInt() ;
a = input.nextInt() ;
b = input.nextInt() ;
l = input.nextInt() ;
r = input.nextInt() ;
c = new long[10000][10000] ;
long ans = 0 ;
init();
for(long i=l; i<=r; i++){
ans = (ans%mod + c[f(i)][k]%mod) %mod ;
}
System.out.println(ans);
}
public static void init() {
for (int i = 0; i < 10000; i++)
for (int j = 0; j <= i; j++)
if (j == 0) c[i][j] = 1;
else c[i][j] = (c[i - 1][j] + c[i - 1][j - 1]) % mod;
}
private static int f(long i){
if(i==1 || i==2){
return 1 ;
}
return (a * f(i-1)%mod + b * f(i-2)%mod)%mod ;
}
}
H题-最大化
思路:判断是否联通,我用的并查集判断你是否联通的,如果不连通,就一定是无穷大,输出-1,如果联通, 我用的bfs去搜索,搜索的轮数num,用(num-1)*D就是答案。AC代码如下:
import java.util.*;
public class Main {
static int [] fa ;
static List<List<Integer>> list ;
static boolean [] vis ;
public static void main(String[] args) {
Scanner input = new Scanner(System.in) ;
int n = input.nextInt() ;
int D = input.nextInt() ;
fa = new int [n+1] ;
vis = new boolean[n+1] ;
int [] inDegree = new int [n+1] ;
list = new ArrayList<>() ;
for(int i=0; i<=n; i++){
list.add(new ArrayList<>()) ;
}
int [][] edge = new int [n+1][n+1] ;
for(int i=1; i<=n; i++){
for(int j=1; j<=n; j++){
edge[i][j] = input.nextInt() ;
if(edge[i][j]==1){ //构建邻接表
list.get(i).add(j) ;
list.get(j).add(i) ;
inDegree[i] ++ ;
inDegree[j] ++ ;
}
}
}
for(int i=1; i<=n; i++){
fa[i] = i ;
}
for(int i=1; i<=n; i++){
for(int j=1; j<=n; j++){
if(edge[i][j]==1){
union(i,j) ;
}
}
}
int ans = 0 ;
for(int i=1; i<=n; i++){
if(i==find(i)){
ans ++ ;
}
}
int min = inDegree[1] ;
int index = 1;
for(int i=2; i<=n; i++){
if(min>inDegree[i]){
min = inDegree[i] ;
index = i ;
}
}
Queue<Integer> queue = new LinkedList<>() ;
int num = 0;
if(ans==1){ //联通
//从入度最少的开始广度优先遍历
queue.add(index) ;
vis[index] = true ;
while(!queue.isEmpty()){
num ++ ;
int size = queue.size() ;
for(int i=0; i<size; i++){
int x = queue.poll() ;
for(int y : list.get(x)){
if(!vis[y]) {
queue.add(y);
vis[y] = true ;
}
}
}
}
System.out.println((num-1)*D);
}else{
System.out.println(-1);
}
}
private static int find(int x){
if(x!=fa[x]){
fa[x] = find(fa[x]) ;
}
return fa[x] ;
}
private static void union(int x, int y){
int root1 = find(x) ;
int root2 = find(y) ;
if(root1==root2){
return ;
}
fa[root1] = root2 ;
}
}
I题-小x的好路-road
思路:题目不难,但是题目描述的晦涩难懂,有种外文谷歌翻译的感觉,哈哈,这题是贪心策略,就是将每个顶点的所有边按升序排序,每次选择两个边权的最大值累加,就是答案,不过这个题对Java选手并不友好,我们使用常用的Scanner类或者BufferedReader读取都判超时,我都想骂娘了,不说了,看一下AC代码吧。这个用时0.6s。
import java.io.*;
import java.util.*;
public class Main {
static List<Integer>[] g ;
public static void main(String[] args) throws IOException {
StreamTokenizer in=new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));
in.nextToken() ;
int n = (int) in.nval ;
int m = n * (n-1) / 2 ;
g = new List[n+1] ;
for(int i=0; i<=n; i++){
g[i] = new ArrayList<>() ;
}
for(int i=1; i<=m; i++){
in.nextToken() ;
int u = (int)in.nval ;
in.nextToken() ;
int v = (int)in.nval ;
in.nextToken() ;
int w = (int)in.nval ;
g[u].add(w) ;
g[v].add(w) ;
}
long ans = 0 ;
for(int i=1; i<=n; i++){
Collections.sort(g[i]);
for(int j=1; j<g[i].size(); j+=2){
ans += g[i].get(j) ;
}
}
out.println(ans);
out.flush();
}
}
我们看一下超时代码,这个用时1.9s,判定超时,大部分的时间都用在处理输入输出,你敢信。
import java.util.*;
public class Main {
static Vector<Integer>[] g ;
public static void main(String[] args) {
Scanner input = new Scanner(System.in) ;
int n = input.nextInt() ;
int m = n * (n-1) / 2 ;
g = new Vector[n+1] ;
for(int i=0; i<=n; i++){
g[i] = new Vector<>() ;
}
for(int i=1; i<=m; i++){
int u = input.nextInt() ;
int v = input.nextInt() ;
int w = input.nextInt() ;
g[u].add(w) ;
g[v].add(w) ;
}
long ans = 0 ;
for(int i=1; i<=n; i++){
Collections.sort(g[i]);
for(int j=1; j<g[i].size(); j+=2){
ans += g[i].get(j) ;
}
}
System.out.println(ans);
}
}
我们再看一下这个,用时1.5s,BufferedReader比Scanner类快一点,但是还是超时。
import java.io.*;
import java.util.*;
public class Main {
static List<Integer>[] g ;
public static void main(String[] args) throws IOException {
BufferedReader input = new BufferedReader(new InputStreamReader(System.in));
int n = Integer.parseInt(input.readLine());
int m = n * (n-1) / 2 ;
g = new List[n+1] ;
for(int i=0; i<=n; i++){
g[i] = new ArrayList<>() ;
}
for(int i=1; i<=m; i++){
String [] a = input.readLine().split("[ ]") ;
int u = Integer.parseInt(a[0]) ;
int v = Integer.parseInt(a[1]) ;
int w = Integer.parseInt(a[2]) ;
g[u].add(w) ;
g[v].add(w) ;
}
input.close();
long ans = 0 ;
for(int i=1; i<=n; i++){
Collections.sort(g[i]);
for(int j=1; j<g[i].size(); j+=2){
ans += g[i].get(j) ;
}
}
System.out.println(ans);
}
}