将定期更新蓝桥杯习题集的解题报告~
#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;
}
}
#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();
}
}
简记:若强行跑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;
}
}
简记:一开始理解错了题意,后来百度的其他人方法,发现是一个玄学的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;
}
}
}
简记:读入有些技巧,如果明白文件输入输出原理的话,会方便不少。
#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();
}
}
#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);
}
}
简记: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);
}
}
题目大意:输入两个数: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);
}
}
简记:
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;
}
}
简记:
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);
}
}
简记:
这次练一下指针形式建树。这个横向输出实在麻烦,预声明了二维字符数组,递归画出,最后输出。
#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);
}
}
简记:
依次在图中删除每一个点,判断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);
}
}
简记:
枚举每条边(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);
}
}
简记:
首先两两组合看成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;
}
}
简记:动态规划
#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);
}
}