蓝桥杯题库 历届试题部分(C++、Java)代码实现(1-15)

文章目录

  • 五、历届试题
    • PREV-1 核桃的数量
    • PREV-2 打印十字图
    • PREV-3 带分数
    • PREV-4 剪格子
    • PREV-5 错误票据
    • PREV-6 翻硬币
    • PREV-7 连号区间数
    • PREV-8 买不到的数目
    • PREV-9 大臣的旅费
    • PREV-10 幸运数
    • PREV-11 横向打印二叉树
    • PREV-12 危险系数
    • PREV-13 网络寻路
    • PREV-14 高僧斗法
    • PREV-15 格子刷油漆

将定期更新蓝桥杯习题集的解题报告~

五、历届试题

PREV-1 核桃的数量

#include 
using namespace std;
int lcm(int x, int y) { return x * y / __gcd(x, y); }
int main() {
    int a, b, c;
    while (scanf("%d%d%d", &a, &b, &c) != EOF) {
        printf("%d\n", lcm(lcm(a, b), c));
    }
}
import java.util.*;
public class Main {

	public static void main(String[] args) {//
		// TODO Auto-generated method stub
		Scanner cin = new Scanner(System.in);
		
		int[] arr = new int[3];
		for (int i = 0;i<3;i++) {
			arr[i] = cin.nextInt();
		}
		System.out.print(minPart(arr[0],minPart(arr[1],arr[2])));
		cin.close();
	}
	private static int minPart(int i, int j) {//
		
		int mul = i*j;
		while(j!=0) {
			int temp = j;
			j = i % j;
			i = temp;
		}
		return mul/i;
	}
}

PREV-2 打印十字图

#include 
using namespace std;
const int bas = 500;
int a[bas][bas];
int mov[8][2] = {{1, 0}, {-1, 0}, {0, 1},  {0, -1},
                 {1, 1}, {1, -1}, {-1, 1}, {-1, -1}};
bool vis[bas][bas];
void print(int n) {
    memset(a, -1, sizeof(a));
    int mid = n / 2;
    a[mid][mid] = 1;
    a[mid + 1][mid] = 1;
    a[mid + 2][mid] = 1;
    a[mid - 1][mid] = 1;
    a[mid - 2][mid] = 1;
    a[mid][mid + 1] = 1;
    a[mid][mid + 2] = 1;
    a[mid][mid - 1] = 1;
    a[mid][mid - 2] = 1;
    for (int i = 0; i < 100; i++) {
        memset(vis, 0, sizeof(vis));
        for (int x = 0; x < n; x++)
            for (int y = 0; y < n; y++) {
                if (a[x][y] != -1) continue;
                int flag = 0;
                for (int c = 0; c < 8; c++) {
                    int tx = x + mov[c][0], ty = y + mov[c][1];
                    if (tx < 0 || tx >= n || ty < 0 || ty >= n ||
                        a[tx][ty] == -1)
                        continue;
                    flag = 1;
                }
                if (flag == 1) {
                    vis[x][y] = 1;
                }
            }
        for (int x = 0; x < n; x++)
            for (int y = 0; y < n; y++) {
                if (vis[x][y] == 1) {
                    if (i & 1)
                        a[x][y] = 1;
                    else
                        a[x][y] = 0;
                }
            }
    }
    a[0][n - 1] = !(n & 1);
    a[0][0] = !(n & 1);
    a[n - 1][n - 1] = !(n & 1);
    a[n - 1][0] = !(n & 1);
}
int main() {
    int n;
    while (scanf("%d", &n) != EOF) {
        print(4 * n + 5);
        for (int i = 0; i < 4 * n + 5; i++) {
            for (int j = 0; j < 4 * n + 5; j++) {
                if (a[i][j] == 0)
                    printf(".");
                else
                    printf("$");
            }
            printf("\n");
        }
    }

    return 0;
}
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int N = scanner.nextInt();
        int Len = (N+1)*2+1;
        // 计算出右下角的图形
        char[][] matrix = new char[Len][Len];
        matrix[0][0] = matrix[0][1] = matrix[0][2] = '$';
        // 计算第一行的值
        for (int i = 3;i<Len;i+=2){
            matrix[0][i] = '.';
            matrix[0][i+1] = '$';
        }
        // 计算倒数第二行的值
        for (int i = 0;i<Len;i++)
            matrix[Len-2][i] = '.';
        matrix[Len-2][Len-3] = '$';
        // 计算倒数第一行的值
        for (int i = 0;i<Len;i++)
            matrix[Len-1][i] = '$';
        matrix[Len-1][Len-1] = '.';
        matrix[Len-1][Len-2] = '.';
        // 计算中间行的值
        for (int i = 1;i<Len-2;i++){
            // 填充第 i 行的值
            if (i%2==1){
                // 如果是奇数行
                int j = 0;
                for (j = 0;j<i;j++){
                    matrix[i][j] = '.';
                }
                matrix[i][i-1] = '$';
                matrix[i][j++] = '.';
                matrix[i][j++] = '.';
                matrix[i][j++] = '.';
                for (int k = 0;k+j<Len;k++){
                    if (k%2==0)matrix[i][j+k] = '$';
                    else matrix[i][j+k] = '.';
                }
            } else {
                // 如果是偶数行
                int j = 0;
                for (j = 0;j<i;j++){
                    matrix[i][j] = '$';
                }
                matrix[i][i-1] = '.';
                matrix[i][j++] = '$';
                matrix[i][j++] = '$';
                matrix[i][j++] = '$';
                for (int k = 0;k+j<Len;k++){
                    if (k%2==0)matrix[i][j+k] = '.';
                    else matrix[i][j+k] = '$';
                }
            }
        }
        for (int i = 0;i<Len;i++){
            StringBuffer stringBuffer = new StringBuffer();
            int hang = Len-1-i;
            for (int j = 0;j<Len-1;j++){
                stringBuffer.append(matrix[hang][Len-1-j]);
            }
            System.out.print(stringBuffer);
            System.out.print(matrix[hang][0]);
            System.out.println(stringBuffer.reverse());
        }
        for (int i = 1;i<Len;i++){
            StringBuffer stringBuffer = new StringBuffer();
            int hang = i;
            for (int j = 0;j<Len-1;j++){
                stringBuffer.append(matrix[hang][Len-1-j]);
            }
            System.out.print(stringBuffer);
            System.out.print(matrix[hang][0]);
            System.out.println(stringBuffer.reverse());
        }
        scanner.close();
    }
}

PREV-3 带分数

简记:若强行跑O(11!)的时间复杂度再O(11)判断是否可行,会超时,需要在dfs过程中,通过维护已经得到的值来剪枝。

#include 
using namespace std;
#define maxn 15
const int bas = 11;
int ans = 0, n, a[maxn], vis[maxn];
void print() {
    for (int i = 0; i < bas; i++) {
        if (a[i] == 0)
            printf("+");
        else if (a[i] == 10)
            printf("/");
        else
            printf("%d", a[i]);
    }
    printf("\n");
}
int cla() {
    int ret = -1;
    int flag = 0, now = 0, mot = 0;  //是否出现过'/'
    for (int i = 0; i < bas; i++) {
        if (a[i] == 0) {  //出现'+'
            if (now == 0) return -1;
            ret = now;
            now = 0;
        } else if (a[i] == 10) {  //出现'/'
            if (now == 0) return -1;
            mot = now;
            now = 0;
        } else {
            now = now * 10 + a[i];
        }
    }
    if ((mot % now != 0) || (now == 0)) return -1;
    // print();
    return ret + mot / now;
}
void dfs(int x, int op, int s, int son, int mot) {  // 0son 1mot 2s
    if (x == 11) {
        if (op != 2) return;
        if ((s == 0) || (son % mot != 0)) return;
        if (s + son / mot == n) ans++;
        return;
    }
    for (int i = 0; i < bas; i++) {
        int top = op, ts = s, tson = son, tmot = mot;
        if (vis[i] == 1) continue;
        if (i == 0) {  //'+'
            if (op != 1 || mot == 0) continue;
            if (son % mot != 0 || son / mot > n) continue;
            top = 2;
        } else if (i == 10) {  //'/'
            if (op != 0) continue;
            if (son == 0) continue;
            top = 1;
        } else {
            if (op == 0)
                tson = son * 10 + i;
            else if (op == 1)
                tmot = mot * 10 + i;
            else
                ts = s * 10 + i;
        }
        vis[i] = 1;
        // a[x]=i;
        dfs(x + 1, top, ts, tson, tmot);
        vis[i] = 0;
    }
}
int main() {
    while (scanf("%d", &n) != EOF) {
        ans = 0;
        memset(vis, 0, sizeof(vis));
        dfs(0, 0, 0, 0, 0);
        printf("%d\n", ans);
    }
    return 0;
}

import java.io.*;
import java.util.*;

class input {
   private
    static BufferedReader br =
        new BufferedReader(new InputStreamReader(System.in));
   private
    static StringTokenizer tokenizer;
   public
    static String next() throws IOException {
        while (tokenizer == null || !tokenizer.hasMoreTokens()) {
            String line = br.readLine();
            if (line == null) {
                throw new IOException();
            }
            tokenizer = new StringTokenizer(line);
        }
        return tokenizer.nextToken();
    }
   public
    static int nextInt() throws IOException { return Integer.parseInt(next()); }
} public class Main {
   public
    static void main(String[] args) throws IOException {
        int n = input.nextInt();
        int count = 0;
        int sum = 0;
        int[] dict = new int[100];
        for (int i = 1; i < n; i++) {
            for (int j = 1; j < 10000; j++) {
                for (int k = 0; k < 10; k++) {
                    dict[k] = 0;
                }
                count = f(i, j, j * (n - i), dict);
                if (count > 9) {
                    break;
                }
                if (dict[0] > 0 || count < 9) {
                    continue;
                }
                for (int k = 1; k < 10; k++) {
                    if (dict[k] != 1) {
                        count = -1;
                        break;
                    }
                }
                if (count == 9) {
                    sum++;
                }
            }
        }
        System.out.println(sum);
    }
    static int f(int a, int b, int c, int[] dict) {
        int count = 0;
        while (a > 0) {
            dict[a % 10]++;
            a /= 10;
            count++;
        }
        while (b > 0) {
            dict[b % 10]++;
            b /= 10;
            count++;
        }
        while (c > 0) {
            dict[c % 10]++;
            c /= 10;
            count++;
        }
        return count;
    }
}

PREV-4 剪格子

简记:一开始理解错了题意,后来百度的其他人方法,发现是一个玄学的dfs+剪枝,最差时间复杂度为:O(2^n*m)。认为没必要费时间练这题~

#include 
using namespace std;
int n, m, a[20][20], ans, sum;
int mov[4][2] = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
bool vis[20][20];
void dfs(int x, int y, int s, int dep) {
    if (dep >= ans || s > sum) return;
    if (s == sum) {
        /*for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++){
                if(vis[i][j])printf("%d ",a[i][j]);
                else printf("0 ");
            }
            printf("\n");
        }*/
        ans = dep;
        return;
    }
    for (int i = 0; i < 4; i++) {
        int tx = x + mov[i][0], ty = y + mov[i][1];
        if (tx <= 0 || tx > n || ty <= 0 || ty > m) continue;
        if (vis[tx][ty]) continue;
        vis[tx][ty] = 1;
        dfs(tx, ty, s + a[tx][ty], dep + 1);
        vis[tx][ty] = 0;
    }
}
int main() {
    scanf("%d%d", &m, &n);
    ans = n * m;
    sum = 0;
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
            scanf("%d", &a[i][j]);
            sum += a[i][j];
        }
    }
    if (sum & 1) {
        printf("0\n");
        return 0;
    }
    sum /= 2;
    memset(vis, 0, sizeof(vis));
    vis[1][1] = 1;
    dfs(1, 1, a[1][1], 1);
    if (ans == n * m)
        printf("0\n");
    else
        printf("%d\n", ans);
    return 0;
}
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class Main {

	private static int M = 0, N = 0;
	private static int sum = 0;
	private static int[][] map = new int[10][10];
 	private static int[][] color = new int[10][10];
 	private static int min_unit_cnt = 0;
	
	public static void main(String[] args) throws IOException {
		
		BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
		String str = bf.readLine();
		
		String[] argNums = str.split(" ");
		M = Integer.parseInt(argNums[0]);
		N = Integer.parseInt(argNums[1]);
		
		for (int i = 0;i < N;++i) {
			String mapLine = bf.readLine();
			String[] nums = mapLine.split(" "); 
			for (int j = 0;j < M;++j) {
				map[i][j] = Integer.parseInt(nums[j]);
				sum += map[i][j];
			}
		}
		
		if (sum % 2 != 0) {
			System.out.println(min_unit_cnt);
			return;
		}
		
		dfs(0,0,0,0);
		System.out.println(min_unit_cnt);	
	}

	private static void dfs(int x, int y, int cnt, int dfs_sum) {
		if (x >= N || y >= M || x < 0 || y < 0 
			|| (min_unit_cnt != 0 && cnt + 1 >= min_unit_cnt)
			|| color[x][y] == 1
			) {
			return;
		}
		dfs_sum = dfs_sum + map[x][y];
		if (dfs_sum > sum ) {
			return ;
		} else if (dfs_sum == sum / 2 ) {
			if (min_unit_cnt == 0 || cnt + 1 < min_unit_cnt) {
				min_unit_cnt = cnt + 1;
			}
			return;
		} else {
			
			color[x][y] = 1;
			
			
			dfs(x, y+1,cnt+1,dfs_sum);
			
			dfs(x+1, y,cnt+1,dfs_sum);
			
			dfs(x, y-1,cnt+1,dfs_sum);
			
			dfs(x-1, y,cnt+1,dfs_sum);
			
			color[x][y] = 0;
			
			return;
		}
	}

}

PREV-5 错误票据

简记:读入有些技巧,如果明白文件输入输出原理的话,会方便不少。

#include 
using namespace std;
#define maxn 1000
int a[maxn], num[maxn];
int main() {
    int n, x;
    scanf("%d", &n);
    n = 0;
    while (scanf("%d", &x) != EOF) {
        a[n++] = x;
    }
    sort(a, a + n);
    int ans = -1, ans2 = -1;
    for (int i = 1; i < n; i++) {
        if (a[i] == a[i - 1]) ans2 = a[i];
        if (a[i] != a[i - 1] + 1 && a[i] != a[i - 1]) ans = a[i] - 1;
    }
    printf("%d %d\n", ans, ans2);
    return 0;
}

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Scanner;

public class Main
{
	
	public static void main(String[] args)
	{
		Scanner in = new Scanner(new BufferedReader(new InputStreamReader(System.in)));
		PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));
		
		int num = in.nextInt();
		List<Integer> list = new ArrayList<Integer>();
		for(int i = 0; i <= num; i++)
		{
			String[] strLine = in.nextLine().split(" ");
			for(int j = 0; j < strLine.length; j++)
			{
				if(strLine[j].equals(""))    continue;
				list.add(Integer.parseInt(strLine[j]));
				//System.out.println(list.get(list.size() - 1));
			}
		}
		
		int min = 100010;
		int max = -1;
		int[] numLine = new int[100010];
		for(int i = 0; i < list.size(); i++)
		{
			numLine[list.get(i)]++;
			min = list.get(i) > min ? min : list.get(i);
			max = list.get(i) > max ? list.get(i) : max;
		}
		int lost = 0;
		int same = 0;
		for(int i = min; i <= max; i++)
			if(numLine[i] == 0)    { lost = i;  break;}
		for(int i = min; i <= max; i++)
			if(numLine[i] == 2)    { same = i;  break;}
		out.println(lost + " " + same);
		out.flush();
	}
}

PREV-6 翻硬币

#include 
using namespace std;
#define maxn 1052
char s[maxn];
int a[maxn], b[maxn];
int main() {
    int n;
    scanf("%s", s);
    n = strlen(s);
    for (int i = 0; i < n; i++) {
        if (s[i] == 'o')
            a[i] = 0;
        else
            a[i] = 1;
    }
    scanf("%s", s);
    for (int i = 0; i < n; i++) {
        if (s[i] == 'o')
            b[i] = 0;
        else
            b[i] = 1;
    }
    int ans = 0;
    for (int i = 0; i < n - 1; i++) {
        if (a[i] != b[i]) {
            ans++;
            a[i + 1] = !a[i + 1];
        }
    }
    if (a[n - 1] != b[n - 1])
        printf("-1\n");  //应该是不可能不能成功
    else
        printf("%d\n", ans);
    return 0;
}

import java.io.*;

class Main{
    static void change(int idx, StringBuilder cur){
        String ex=cur.substring(idx, idx+2);
        if(ex.equals("**")){
            cur.replace(idx, idx+2, "oo");
        }else if(ex.equals("*o")){
            cur.replace(idx, idx+2, "o*");
        }else if(ex.equals("o*")){
            cur.replace(idx, idx+2, "*o");
        }else{
            cur.replace(idx, idx+2, "**");
        }
    }
    
    public static void main(String[]args) throws IOException{
        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
        StringBuilder st = new StringBuilder(in.readLine());
        String ed = in.readLine();
        
        int n = st.length();
        int step=0;
        for(int i=0; i<n-1; i++){
            char a = st.toString().charAt(i);
            char b = ed.charAt(i);
            
            if(a==b) continue;
            else{
                step+=1;
                change(i, st);
            }
        }
        
        System.out.println(step);
    }
}

PREV-7 连号区间数

简记:n方暴力就可以过,没想到巧妙地枚举方法可以做到nlogn。

#include 
using namespace std;
const int maxn = 100052;
int a[maxn];
int main() {
    int ans, n;
    scanf("%d", &n);
    for (int i = 0; i < n; i++) {
        scanf("%d", &a[i]);
    }
    ans = 0;
    for (int l = 0; l < n; l++) {
        ans++;
        int min0 = a[l], max0 = a[l];
        for (int r = l + 1; r < n; r++) {
            min0 = min(min0, a[r]);
            max0 = max(max0, a[r]);
            if (max0 - min0 == r - l) ans++;
        }
    }
    printf("%d\n", ans);
    return 0;
}

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class Main {
    static int N = 100010;
    static int[] f = new int[N];
    public static void main(String[] args) throws NumberFormatException, IOException {
        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
        int n = Integer.parseInt(reader.readLine().trim());
        String[] s1 = reader.readLine().split(" ");
        for(int i = 1;i <= n;i++) f[i] = Integer.parseInt(s1[i - 1]);
        int res = 0;
        for(int i = 1;i <= n;i++)
        {
            int minv = Integer.MAX_VALUE;
            int maxv = Integer.MIN_VALUE;
            for(int j = i;j <= n;j++)
            {
                minv = Math.min(minv, f[j]);
                maxv = Math.max(maxv, f[j]);
                if(maxv - minv == j - i) res ++;
            }
        }
        System.out.println(res);
    }
}

PREV-8 买不到的数目

题目大意:输入两个数:a,b,找出最大的c满足c不能表示成an+bm(n,m∈N*)
思路:打表找规律

#include 
#include 
#include 
using namespace std;
int dp[1050] = {0};

int main() {
    int a, b;
    cin >> a >> b;
    if (a > b)  // a
    {
        int c = a;
        a = b;
        b = c;
    }
    int maxx = 0;
    for (int i = 1; i < b; i++) {
        int x = i;
        while (1) {
            if (x % a == 0) break;
            x += b;
        }
        // cout<
        if (maxx < x) maxx = x;
    }

    cout << maxx - b;
    return 0;
}

import java.io.BufferedReader;
import java.io.InputStreamReader;

public class Main {
	public static void main(String[] args) throws Throwable {
		BufferedReader buf = new BufferedReader(new InputStreamReader(System.in));
		String strNum = buf.readLine();
		String[] num = strNum.split(" ");
		int a, b;
		a = Integer.valueOf(num[0]);
		b = Integer.valueOf(num[1]);
		if (a > b) {
			int tem = a;
			a = b;
			b = tem;
		}
		int c = a * b;
		int tem = c;
		while (tem > 0) {
			if (tem % a == 0)
				tem = --c;
			else if (tem % b == 0)
				tem = --c;
			else
				tem -= b;
		}
		System.out.println(c);
	}
}

PREV-9 大臣的旅费

简记:
1.问题等价于求一棵树的重心
2.实测点数n<=10000,最大路费不超过signed int。

#include 
using namespace std;
#define maxn 10052
struct node {
    int pos, val;
    node() {}
    node(int p, int v) {
        pos = p;
        val = v;
    }
};
int f(int x) { return x * 10 + (1 + x) * x / 2; }
vector<node> u[maxn];
int dis[maxn];
int dfs(int x, int fa, int h) {
    for (int i = 0; i < u[x].size(); i++) {
        if (u[x][i].pos == fa) continue;
        dfs(u[x][i].pos, x, h + u[x][i].val);
    }
    return dis[x] = h;
}
int main() {
    int n;
    scanf("%d", &n);
    for (int i = 0; i < n - 1; i++) {
        int s, t, w;
        scanf("%d%d%d", &s, &t, &w);
        u[s].push_back(node(t, w));
        u[t].push_back(node(s, w));
    }
    dfs(1, -1, 0);
    int root = 0;
    for (int i = 1; i <= n; i++) {
        if (root == 0 || dis[i] > dis[root]) root = i;
    }
    // printf("root=%d\n",root);
    dfs(root, -1, 0);
    int ans = 0;
    for (int i = 1; i <= n; i++) {
        if (ans == 0 || dis[i] > dis[ans]) ans = i;
    }
    // printf("ans=%d\n",ans);
    printf("%d\n", f(dis[ans]));
    return 0;
}
import java.io.BufferedInputStream;
import java.io.IOException;
import java.util.ArrayList;

public class Main
{
	private static BufferedInputStream in = new BufferedInputStream(System.in);
	private static ArrayList<Node> n = new ArrayList<Node>();
	private static Integer dis = 0;
	private static Integer pow = 0;
	
	public static void main(String[] args) throws IOException
	{
		int size = readInt();
		
		for(int i=0; i<size; i++)
		{
			n.add(null);
		}
		
		for(int i=1; i<size; i++)
		{
			int x = readInt()-1;
			int y = readInt()-1;
			int d = readInt();
			
			Node node = new Node();
			node.nextSide = n.get(x);
			node.con = y;
			node.power = d;
			n.set(x, node);
			
			node = new Node();
			node.nextSide = n.get(y);
			node.con = x;
			node.power = d;
			n.set(y, node);
		}
		
		away(0, 0, -1);
		pow = 0;
		away(dis, 0, -1);
		System.out.println(pow * 10 + (1 + pow) * pow /2);
	}
	
	private static void away(int index, int power, int from)
	{
		if(pow < power)
		{
			pow = power;
			dis = index;
		}
		
		Node node = n.get(index);
		
		while(node != null)
		{
			if(node.con == from)
			{
				node = node.nextSide;
				continue;
			}
			
			away(node.con, power + node.power, index);
			
			node = node.nextSide;
		}
	}
	
	private static int readInt() throws IOException
	{
		int i,sum=0;
		
		while(((i=in.read())&48) != 48 || i>57);
		
		for(;(i&56) == 48 || (i&62) == 56; i=in.read())
			sum = sum*10 + (i&15);
		
		return sum;
	}
	
	private static class Node
	{
		int power;
		int con;
		Node nextSide;
	}
}

PREV-10 幸运数

简记:
1.一般这种求区间[L,R]之间个数的,变成求[1,R]个数-[1,L-1]个数。
2.乍一看,平均下来每次压缩是个logn级别的操作,权当一试。
3.1e6超时,5e5优化到了极致,可以通过数据,但是应该还是有问题,我觉得是题目问题。

#include 
using namespace std;
#define maxn 500052
int a[maxn];
int f(int x, int len) {  //将a数组中下标为x的倍数的位置的数字删除,返回数组长度
    if (x > len) return len;
    int cnt = x;
    for (int i = x; i <= len; i++) {
        if (i % x == 0) continue;
        a[cnt++] = a[i];
    }
    a[cnt] = 0;
    return cnt - 1;
}
int init() {
    int ret = 1;
    int len = maxn / 2;
    for (int i = 1; i <= len; i++) {
        a[i] = i * 2 - 1;
    }
    ret++;
    while (a[ret] != 0) {
        if (a[ret] > len) break;
        /*printf("ans[%d]=%d  ",ret,a[ret]);
        for(int i=1;i<=len;i++){
            printf("%d ",a[i]);
        }
        printf("\n");*/
        len = f(a[ret], len);
        ret++;
    }
    return ret;
}
int main() {
    init();
    int n, m;
    scanf("%d%d", &n, &m);
    int ans = 0, flag = 0;
    for (int i = 0; a[i] < m; i++) {
        if (a[i] > n) flag = 1;
        if (flag == 1) ans++;
    }
    printf("%d\n", ans);
}
import java.util.Scanner;

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;
		}
		int l = 1;// 幸运数下标
		while (true) {
			int p = l + 1;// 指向数字向前移动的位置
			for (int i = l + 1; i < n; i++) {
				if ((i + 1) % a[l] != 0) {
					a[p] = a[i];
					p++;
				}
				if (a[p] > n)
					break;
			}
			l++;
			if (a[l] >= n)
				break;
		}
		int count = 0;
		for (int i = 0; i < n; i++) {
			if (a[i] >= n)
				break;
			if (a[i] > m)
				count++;
		}
		System.out.println(count);
	}
}

PREV-11 横向打印二叉树

简记:
这次练一下指针形式建树。这个横向输出实在麻烦,预声明了二维字符数组,递归画出,最后输出。

#include 
using namespace std;
#define maxn 1052
struct node {
    int data, size;
    node *l, *r;
};
node *build_node(int data) {
    node *ret = new node;
    ret->data = data;
    ret->l = NULL;
    ret->r = NULL;
    ret->size = 1;
}
struct sort_tree {
    int pos[10052];  // pos[x]表示x为第pos[x]大
    node *root = new node;
    bool empty = 1;
    int size = 0, cnt;
    char mp[105][1000];
    void draw(node *o, int y, bool flag) {  //第y列加入o
        int now = o->data, x = pos[o->data], ty = y, k = 0;
        char p[10] = {0};
        while (now > 0) {
            p[k++] = now % 10 + '0';
            now /= 10;
        }
        if (flag == 0) {
            mp[x][ty++] = '-';
        }
        for (int i = k - 1; i >= 0; i--, ty++) {  //画数字
            mp[x][ty] = p[i];
        }
        if (o->l != NULL || o->r != NULL) {  //画后缀“-|”
            mp[x][ty++] = '-';
            mp[x][ty] = '|';
        }
        if (o->l != NULL)  //向下画‘|’
            for (int i = x; i <= pos[o->l->data]; i++) {
                mp[i][ty] = '|';
            }
        if (o->r != NULL)  //向上画‘|’
            for (int i = pos[o->r->data]; i <= x; i++) {
                mp[i][ty] = '|';
            }
        if (o->l != NULL || o->r != NULL) ty++;
        mp[x][ty] = '\0';

        if (o->r != NULL) {  //画右子树
            draw(o->r, ty, 0);
        }
        if (o->l != NULL) {  //画左子树
            draw(o->l, ty, 0);
        }
    }
    void out() {
        for (int i = 0; i <= size; i++) {
            for (int j = 0; j < 1000; j++) {
                mp[i][j] = '.';
            }
        }
        draw(root, 0, 1);
        for (int i = 1; i <= size; i++) {
            printf("%s\n", mp[i]);
        }
    }
    void print(node *x) {
        if (x->r != NULL) {
            print(x->r);
        }
        // printf("%d ",x->data);
        pos[x->data] = cnt++;
        if (x->l != NULL) {
            print(x->l);
        }
    }
    void print() {
        memset(pos, -1, sizeof(pos));
        cnt = 1;
        print(root);
    }
    void add(node *x, int v) {
        x->size++;
        if (x->data > v) {
            if (x->l == NULL)
                x->l = build_node(v);
            else
                add(x->l, v);
        } else {
            if (x->r == NULL)
                x->r = build_node(v);
            else
                add(x->r, v);
        }
    }
    void add(int v) {
        size++;
        if (empty) {
            root->data = v;
            root->l = NULL;
            root->r = NULL;
            root->size = 1;
            empty = 0;
        } else
            add(root, v);
    }
};
int main() {
    // freopen("in.txt","r",stdin);
    sort_tree x;
    int n;
    while (scanf("%d", &n) != EOF) {
        x.add(n);
    }
    x.print();
    x.out();
    return 0;
}
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;

public class Main {

	 static int n;
	    static int[] a=new int[108];
	    static int[] left;
	    static int[] right;
	    static int[] level;
	    static int maxl=0;
	    static int M,N;
	    static char[][] map;
	    static boolean[] flag;
	    static boolean[] flag2;
	    
	    static void add(int root,int index)
	    {
	        if(a[index]<a[root])
	            if(left[root]==0) { left[root]=index; level[index]=level[root]+1; if(level[index]>maxl) maxl=level[index]; }
	            else add(left[root],index);
	        else
	            if(right[root]==0) { right[root]=index; level[index]=level[root]+1; if(level[index]>maxl) maxl=level[index]; }
	            else add(right[root],index);
	    }
	    
	    static void Fill(int root,int x,int y)
	    {
	        int lvl=level[root]+1;
	        String num=String.valueOf(a[root]);
	        int len=num.length();
	        flag[x]=true;
	        for(int i=0;i<len;i++)
	        {
	            map[x][y-i]=num.charAt(i);
	            int h=2<<(maxl-lvl);
	            for(int j=1;j<h;j++) { map[x+j][y-i]='.'; map[x-j][y-i]='.'; }
	        }
	        if(left[root]==0 && right[root]==0 && level[root]<maxl) flag2[x]=true;
	        if(left[root]!=0)
	            Fill(left[root],x+(2<<(maxl-lvl))/2,y-8);
	        if(right[root]!=0)
	            Fill(right[root],x-(2<<(maxl-lvl))/2,y-8);
	    }
	    
	    public static void main(String[] args) throws IOException {
	        BufferedReader bfr = new BufferedReader(new InputStreamReader(System.in));
	        StringTokenizer tok=new StringTokenizer(bfr.readLine());
//	      long begin=System.currentTimeMillis();
	        int i,j;
	        for(i=1;tok.hasMoreTokens();i++) a[i]=Integer.parseInt(tok.nextToken());
	        n=i;
	        left =new int[n];
	        right =new int[n];
	        level=new int[n];
	        left[0]=1; right[0]=1; level[0]=0; level[1]=1;
	        for(i=2;i<n;i++)
	            add(1,i);
	        M=(2<<(maxl-1))-1;
	        N=8*maxl-3;
	        map=new char[M][N];
	        flag=new boolean[M];
	        flag2=new boolean[M];
	        for(int l=1;l<maxl;l++)
	        {
	            int ty=l*8-1;
	            int start=(2<<(l-1))-1,d=(2<<l);
	            for(i=0;i<M;i++) map[i][ty]=map[i][ty-1]=map[i][ty-2]='.'; 
	            for(i=start;i<M;i+=d)
	            {
	                map[i][ty]='-';
	                int hei=(2<<(l-1))/2;
	                for(int ii=0;ii<=hei;ii++)
	                {
	                    map[i+ii][ty-1]='|';
	                    map[i-ii][ty-1]='|';
	                }
	                map[i+hei][ty-2]='-';
	                map[i-hei][ty-2]='-';
	            }
	        }
	        Fill(1,M/2,N-1);
	        
	        for(i=0;i<M;i++)
	        {
	            if(flag[i])
	            {
	                for(j=0;;j++) if(map[i][j]!=0 && map[i][j]!='.') break;
	                int jj;
	                for(jj=N-1;jj>j+1;jj--) if(map[i][jj]!=0) System.out.print(map[i][jj]);
	                if(!flag2[i]) System.out.print(map[i][jj]+""+map[i][jj-1]);
	                System.out.println();
	            }
	        }
//	      System.out.println(System.currentTimeMillis()-begin);
	    }
	}

PREV-12 危险系数

简记:
依次在图中删除每一个点,判断s到t是否依然连通,时间复杂度O(n*m)。直觉感觉应该是还有更快的办法,没认真想。

#include 
using namespace std;
const int maxn = 1005;
const int maxm = 2005;
struct Graph {
    vector<int> a[maxn];
    bool vis[maxn];
    int n, m;
    void input() {
        scanf("%d%d", &n, &m);
        for (int i = 0; i < m; i++) {
            int ss, tt;
            scanf("%d%d", &ss, &tt);
            a[ss].push_back(tt);
            a[tt].push_back(ss);
        }
    }
    void dfs(int x, int del) {
        vis[x] = 1;
        for (int i = 0; i < a[x].size(); i++) {
            if (a[x][i] == del || vis[a[x][i]]) continue;
            dfs(a[x][i], del);
        }
    }
    int cla(int s, int t) {
        int ret = 0;
        for (int i = 1; i <= n; i++) {
            if (i == s || i == t) continue;
            memset(vis, 0, sizeof(vis));
            dfs(s, i);
            if (vis[t] == 0) ret++;
        }
        return ret;
    }
};
int main() {
    Graph ans;
    ans.input();
    int s, t;
    scanf("%d%d", &s, &t);
    printf("%d\n", ans.cla(s, t));
    return 0;
}

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.StringTokenizer;

public class Main {

	static int n,m;
	public static void main(String[] args) throws IOException {
		BufferedReader bfr=new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer tok=new StringTokenizer(bfr.readLine());
//		long begin=System.currentTimeMillis();
		n=Integer.parseInt(tok.nextToken());
		m=Integer.parseInt(tok.nextToken());
		ArrayList<Integer>[] way=new ArrayList[n];
		int count=0;
		int i;
		for(i=0;i<n;i++) way[i]=new ArrayList<Integer>();
		for(i=0;i<m;i++)
		{
			tok=new StringTokenizer(bfr.readLine());
			int x=Integer.parseInt(tok.nextToken())-1, y=Integer.parseInt(tok.nextToken())-1;
			way[x].add(y); way[y].add(x);
		}
		tok=new StringTokenizer(bfr.readLine());
		int g1=Integer.parseInt(tok.nextToken())-1, g2=Integer.parseInt(tok.nextToken())-1;
		
		for(i=0;i<n;i++)
		{
			if(i==g1 || i==g2) continue;
			boolean[] flag=new boolean[n];
			int[] que=new int [n];
			int front=0,rear=1;
			que[0]=g1;
			while(front<rear)
			{
				for(int p=0;p<way[que[front]].size();p++)
				{
					if(way[que[front]].get(p)==i) continue;
					if (!flag[way[que[front]].get(p)])
					{
						que[rear] = way[que[front]].get(p);
						flag[que[rear]]=true;
						if(que[rear]==g2) break;
						rear++;
					}
				}
				if(flag[g2]) { count++; break; }
				front++;
			}
		}
		System.out.println(n-2-count);
//		System.out.println(System.currentTimeMillis()-begin);
	}
}

PREV-13 网络寻路

简记:
枚举每条边(u,v),以这条边为中间边的合法边数为:(和u相连的点数-1)*(和v相连的点数-1)

#include 
using namespace std;
typedef long long int qq;
const int node_size = 10005;
const int edge_size = 100005;
struct Graph {
    vector<int> u[node_size];
    int n, m;
    void clear() {
        for (int i = 0; i < node_size; i++) {
            u[i].clear();
        }
    }
    void add_edge(int s, int t) {
        u[s].push_back(t);
        u[t].push_back(s);
    }
    void input() {
        scanf("%d%d", &n, &m);
        for (int i = 0; i < m; i++) {
            int ss, tt;
            scanf("%d%d", &ss, &tt);
            add_edge(ss, tt);
        }
    }
    qq cla() {
        qq ret = 0;
        for (int i = 1; i <= n; i++) {
            for (int j = 0; j < u[i].size(); j++) {
                ret += (u[i].size() - 1) * (u[u[i][j]].size() - 1);
            }
        }
        return ret;
    }
};
int main() {
    Graph ans;
    ans.clear();
    ans.input();
    printf("%lld\n", ans.cla());
    return 0;
}


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.StringTokenizer;

public class Main {
	
	public static void main(String[] args) throws IOException {
		BufferedReader bfr = new BufferedReader(
				new InputStreamReader(System.in));
		StringTokenizer tok = new StringTokenizer(bfr.readLine());
		int n = Integer.parseInt(tok.nextToken());
		int m = Integer.parseInt(tok.nextToken());
		int i, count = 0;
		ArrayList<Integer>[] way = new ArrayList[n];
		
		for (i = 0; i < n; i++)
			way[i] = new ArrayList<Integer>();
		
		for (i = 0; i < m; i++) {
			tok = new StringTokenizer(bfr.readLine());
			int x = Integer.parseInt(tok.nextToken()) - 1;
			int y = Integer.parseInt(tok.nextToken()) - 1;
			way[x].add(y);
			way[y].add(x);
		}

		for (i = 0; i < n; i++) {
			int a = i, ll = way[i].size();
			for (int ii = 0; ii < ll; ii++) {
				int aa = way[a].get(ii);
				int lll = way[aa].size();
				for (int iii = 0; iii < lll; iii++) {
					int aaa = way[aa].get(iii);
					if (aaa == a)
						continue;
					count += way[aaa].size();
					count--;
					
				}
			}
		}
		System.out.println(count);
	}
}

PREV-14 高僧斗法

简记:
首先两两组合看成nim博奕问题,奇数个就在最高点加一个。但是目标是一定要优先移动最左边的。有个坑点,对于一对点,可以变大也可以变小。

#include 
using namespace std;
const int maxn = 10005;
int a[maxn], c[maxn], n;
int main() {
    n = 0;
    while (scanf("%d", &a[n]) != EOF) {
        n++;
    }
    if (n & 1) {
        a[n] = a[n - 1] + 1;
        n++;
    }
    int ans = 0;
    for (int i = 0, j = 0; i < n; j++, i += 2) {
        c[j] = a[i + 1] - a[i] - 1;
        ans ^= c[j];
    }
    // printf("ans=%d\n",ans);
    if (ans == 0) {
        printf("-1\n");
    } else {
        int m = n / 2;
        for (int i = 0; i < m; i++) {
            int t = ans ^ c[i];
            if (t < c[i]) {
                printf("%d %d", a[i * 2], a[i * 2] + c[i] - t);
                break;
            } else if (i * 2 + 2 < n && a[i * 2] + t + 1 < a[i * 2 + 2]) {
                printf("%d %d", a[i * 2 + 1], a[i * 2] + t + 1);
                break;
            }
        }
    }
    return 0;
}
import java.util.Scanner;

public class Main{

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner sc=new Scanner(System.in);
		String A=sc.nextLine();
		String[] arrayA=A.split(" ");
		int[] a=new int[arrayA.length];
		for(int i=0;i<a.length;i++){
			a[i]=Integer.valueOf(arrayA[i]);
		}
		//传入的数组a为小和尚所站的位置
		solve(a);
	}
	//任何无偏的游戏理论上可以转换为尼姆堆
	private static void solve(int[] a) {
		// TODO Auto-generated method stub
		for(int i=0;i<a.length-1;i++)
			for(int k=a[i]+1;k<a[i+1];k++){
				int old=a[i];
				try{
					a[i]=k;//试探
					if(f(a)==false){
						System.out.println(old+" "+k);
						return;
					}
				}finally{
					a[i]=old;//回溯
				}
			}
	}
	private static boolean f(int[] a) {
		// TODO Auto-generated method stub
		int sum=0;
		for(int i=0;i<a.length-1;i+=2){
			sum^=(a[i+1]-a[i]-1);
		}
		return sum!=0;
	}

}

PREV-15 格子刷油漆

简记:动态规划

#include 
using namespace std;
typedef long long qq;
const qq mod = 1000000007;
const int maxn = 1005;

qq a[maxn];
qq b[maxn];  //不能直接使用公式,会超出范围
int main() {
    int n;
    scanf("%d", &n);
    if (n == 1) {
        printf("2\n");
        return 0;
    }

    memset(a, 0, sizeof(a));
    b[1] = 1;
    for (int i = 2; i <= n; i++) {
        b[i] = b[i - 1] * 2 % mod;
    }
    a[1] = 1;
    a[2] = 6;
    for (int i = 3; i <= n; i++) {
        a[i] = a[i - 2] * 4 + a[i - 1] * 2 + b[i];
        a[i] %= mod;
    }
    qq sum = 0;
    for (int i = 2; i < n; i++) {
        sum += (b[n - i + 1] * a[i - 1] + b[i] * a[n - i]) * 4;
        sum %= mod;
    }
    sum += a[n] * 4;
    sum %= mod;
    printf("%lld\n", sum);
    return 0;
}

import java.util.Scanner;

public class Main {
	public static void main(String[] args) {
		Scanner scan=new Scanner(System.in);
		int n=scan.nextInt();
		long a[]=new long[n+1];
		long b[]=new long[n+1];
		long sum;
		b[1]=1;
		for(int i=2;i<=n;i++){
			b[i]=2*b[i-1]%1000000007;
		}
		a[1]=1;a[2]=6;
		for(int i=3;i<=n;i++){
			a[i]=(2*a[i-1]+b[i]+4*a[i-2])%1000000007;
		}
		sum=(4*a[n])%1000000007;
		for(int i=2;i<n;i++){
			sum+=((8*b[i-1]*a[n-i])%1000000007+(8*b[n-i]*a[i-1])%1000000007)%1000000007;//必须每个项都取余,防止有大于这个数的情况
			sum%=1000000007;
		}
		System.out.println(sum);
	}
}

你可能感兴趣的:(蓝桥杯)