提交 299aff85 编写于 作者: qq_36480062's avatar qq_36480062

commit

上级 fc0abbb2
package 前缀和差分;
import java.util.Arrays;
public class 差分 {
public static void main(String[] args) {
int arr[] = {3, 5, 1, 6, 9};
int[] b = new int[20];
for (int i = 1; i < arr.length; i++) {
b[i] = arr[i] - arr[i - 1];
}
System.out.println(Arrays.toString(b));
b[1] += 2;
b[5] -= 2;
for (int i = 1; i < 5; i++) {
arr[i] = b[i] + arr[i - 1];
}
System.out.println(Arrays.toString(arr));
b[2] += 3;
b[5] -= 3;
int t = 0;
for (int i = 1; i < 5; i++) {
arr[i] = b[i] + arr[i - 1];
}
System.out.println(Arrays.toString(arr));
}
}
package 前缀和差分;
/**
*
*/
public class 激光炸弹 {
public static void main(String[] args) {
}
}
package 数学;
import java.util.Scanner;
import static java.lang.System.in;
/**
* 给定一个n*n矩阵A,和一个整数k
* 求S=A+A^2+A^3+A^k并对k取模
* https://www.cnblogs.com/hadilo/p/5903514.html
* 矩阵乘法满足乘法结合律和交换律
* A+A^2=A(I+A)
* A+A^2+A^3+A^4=(A+A^2)(I+A^2)
* A^1+A^2+A^3+A^4+A^5+A^6=(A^1+A^2+A^3)(I+A^3)
* 如果sum(n)=A+A^2+A^3+A^k
* 如果n是偶数sum(n)=sum(n/2)(I+(A^n/2))
* 符合递归的性质,(A^1+A^2+A^3+...+A^k/2)(I+(A^k/2))
* 如果n是奇数sum(n)=sum(n-1)+A^n 求比它低1次方的再加上A^n
*/
public class POJ3233矩阵乘法 {
public static void main(String[] args) {
Scanner sc = new Scanner(in);
n = sc.nextInt();
m = sc.nextInt();
kk = sc.nextInt();//mod数
long[][] a = new long[n][n];
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
a[i][j] = sc.nextLong();
}
}
long[][] res = sum(a, m);
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
System.out.print(res[i][j] + " ");
}
System.out.println();
}
}
static int m, kk, n = 0;
static long[][] sum(long[][] a, int k) {
if (k == 1) return a;
int R = a.length, C = a[0].length;
long[][] c = new long[n][n];
for (int i = 0; i < R; i++) {
c[i][i] = 1;
}
c = add(c, quickPow(a, k >> 1));
c = mul(c, sum(a, k >> 1));
if ((k & 1) == 1) {
c = add(c, quickPow(a, k));
}
return c;
}
static long[][] mul(long[][] a, long[][] b) {
int R = a.length, C = b[0].length;
long[][] res = new long[n][n];
for (int i = 0; i < a.length; i++) {
for (int j = 0; j < b[0].length; j++) {
for (int k = 0; k < b.length; k++) {
res[i][j] = (res[i][j] + a[i][k] * b[k][j]) % kk;
}
}
}
return res;
}
static long[][] add(long[][] a, long[][] b) {
int R = a.length, C = a[0].length;
long[][] res = new long[n][n];
for (int i = 0; i < R; i++) {
for (int j = 0; j < C; j++) {
res[i][j] = b[i][j] + a[i][j];
res[i][j] %= kk;
}
}
return res;
}
static long[][] quickPow(long[][] a, int k) {
long[][] tem = a.clone();
int R = a.length, C = a[0].length;
long[][] res = new long[n][n];
for (int i = 0; i < R; i++) {
res[i][i] = 1;
}
while (k != 0) {
if ((k & 1) == 1) {
res = mul(res, tem);
}
tem = mul(tem, tem);
k >>= 1;
}
return res;
}
}
package 数学;
import java.util.Scanner;
import static java.lang.System.in;
/**
* 90. 64位整数乘法
* 求 a 乘 b 对 p 取模的值。
* 输入格式
* 第一行输入整数a,第二行输入整数b,第三行输入整数p。
* 输出格式
* 输出一个整数,表示a*b mod p的值。
* 数据范围
* 1≤a,b,p≤1018
* 输入样例:
* 3
* 4
* 5
* 输出样例:
* 2
* <p>
* 类似快速幂:
* a*b转换成加法
* a+a+a 加法操作b次
* b次转换成2进制
* a 2a 4a 8a 16a 32a
* 每次翻2倍,转换成2进制
* 乘法转加法,快速幂思想
*/
public class 快速乘 {
public static void main(String[] args) {
Scanner sc = new Scanner(in);
long a = sc.nextLong();
long b = sc.nextLong();
long p = sc.nextLong();
System.out.println(ks(a, b, p));
}
//转换为快速加法,a*b
static long ks(long a, long b, long p) {
long tem = a;
long res = 0;
while (b != 0) {
if ((b & 1) == 1) {
res += tem % p;
res %= p;
}
tem *= 2 % p;
b >>= 1;
}
return res;
}
}
package 数学;
import java.util.Scanner;
import static java.lang.System.in;
/**
* 89. a^b
* 求 a 的 b 次方对 p 取模的值。
* 输入格式
* 三个整数 a,b,p ,在同一行用空格隔开。
* 输出格式
* 输出一个整数,表示a^b mod p的值。
* 数据范围
* 0≤a,b,p≤109
* 输入样例:
* 3 2 7
* 输出样例:
* 2
* 如3^7
* 7的二进制表示111
* 3^1=3
* 3^2=9
* 3^4=81
* 3^8=...
* 可以化成3次操作
*/
public class 快速幂 {
public static void main(String[] args) {
Scanner sc = new Scanner(in);
long a = sc.nextLong();
long b = sc.nextLong();
long p = sc.nextLong();
System.out.println(ks(a, b, p));
}
static long ks(long a, long b, long p) {
long res = 1 % p;//初始化为1,因为0*任何数都为0
//有一个很坑的数据,p为0就不会进入循环,则初始1就mod p
long tem = a;
while (b != 0) {
if ((b & 1) == 1) {
res = res * tem % p;//要这一位,res就加上结果
res %= p;
}
tem *= tem % p;//自增
tem %= p;//多次mod防越界
b >>= 1;//去掉最低位
}
return res;
}
}
package 数学;
/**
* 矩阵的加减法
* 把矩阵对应的数字相加或相加就行了
* 矩阵乘以一个数字,把该数字乘以矩阵的所有数字就可以了
* <p>
* 矩阵乘法:
* 一个大小为n*m的矩阵和一个大小为m*r的矩阵可以相乘
* 最终得到一个n*r的矩阵,不可以交换位置,不满足交换律
* 第一个矩阵的列数,必须等于第二个矩阵的行数
* 如何第一行乘以第一列的值相加就是结果矩阵的第一个数
* 单位矩阵,就是对角线为1的矩阵,乘以任何一个非零矩阵都等于它自己
*/
public class 矩阵 {
public static void main(String[] args) {
}
//矩阵乘法
static long[][] mul(long[][] a, long[][] b) {
int R = a.length, C = b[0].length;
long[][] res = new long[R][C];
for (int i = 0; i < a.length; i++) {
for (int j = 0; j < b[0].length; j++) {
for (int k = 0; k < b.length; k++) {
res[i][j] += a[i][k] * b[k][j];
}
}
}
return res;
}
//矩阵加法
static long[][] add(long[][] a, long[][] b) {
int R = a.length, C = a[0].length;
long[][] res = new long[R][C];
for (int i = 0; i < R; i++) {
for (int j = 0; j < C; j++) {
res[i][j] = b[i][j] + a[i][j];
}
}
return res;
}
//矩阵快速幂
static long[][] quickPow(long[][] a, int k) {
long[][] tem = a;
int R = a.length, C = a[0].length;
long[][] res = new long[R][C];
for (int i = 0; i < R; i++) {
if (i < C)
res[i][i] = 1;
}
while (k != 0) {
if ((k & 1) == 1) {
res = mul(res, tem);
}
tem = mul(tem, tem);
k >>= 1;
}
return res;
}
}
package 递归;
import java.util.ArrayList;
import java.util.Scanner;
import static java.lang.System.in;
/**
* 94. 递归实现排列型枚举
* 把 1~n 这 n 个整数排成一行后随机打乱顺序,输出所有可能的次序。
* 输入格式
* 一个整数n。
* 输出格式
* 按照从小到大的顺序输出所有方案,每行1个。
* 首先,同一行相邻两个数用一个空格隔开。
* 其次,对于两个不同的行,对应下标的数一一比较,字典序较小的排在前面。
* 数据范围
* 1≤n≤9
* 输入样例:
* 3
* 输出样例:
* 1 2 3
* 1 3 2
* 2 1 3
* 2 3 1
* 3 1 2
* 3 2 1
* 排列型枚举,n个数,有n个坑,第一个坑有n种选择,第二个坑有n-1中选择,第n个坑只有一种选择
* 第一个坑的n种选择,是平行的,
*/
public class 排列枚举 {
public static void main(String[] args) {
Scanner sc = new Scanner(in);
n = sc.nextInt();
dfs(0, 0);
}
static int n = 3;
static ArrayList<Integer> path = new ArrayList<Integer>();
//u代表结果path有多少个
static void dfs(int u, int state) {//state通过位运算作为vis数字,
if (u == n) {
for (Integer w : path) {
System.out.print(w + " ");
}
System.out.println();
return;
}
for (int i = 0; i < n; i++) {//枚举n种平行选择
if (!(((state >> i) & 1) == 1)) {//如果这个数字没被选,就选
path.add(i + 1);
dfs(u + 1, state | (1 << i));//选上
path.remove(path.size() - 1);//恢复状态
}
}
}
}
package 递归;
/**
* 93. 递归实现组合型枚举
* 1~n n 个整数中随机选出 m 输出所有可能的选择方案
* 输入格式
* 两个整数 n,m ,在同一行用空格隔开
* 输出格式
* 按照从小到大的顺序输出所有方案每行1个
* 首先同一行内的数升序排列相邻两个数用一个空格隔开
* 其次对于两个不同的行对应下标的数一一比较字典序较小的排在前面例如1 3 5 7排在1 3 6 8前面)。
* 数据范围
* n>0 ,
* 0mn ,
* n+(nm)25
* 输入样例
* 5 3
* 输出样例
* 1 2 3
* 1 2 4
* 1 2 5
* 1 3 4
* 1 3 5
* 1 4 5
* 2 3 4
* 2 3 5
* 2 4 5
* 3 4 5
*/
public class 组合m个数 {
public static void main(String[] args) {
// Scanner sc = new Scanner(in);
// n = sc.nextInt();
// m = sc.nextInt();
long l = System.nanoTime();
dfs(0, 0, 0);
long e = System.nanoTime();
System.out.println(e - l);
}
static int m = 15, n = 10;
//枚举到第u位 ,sum是当前选了几个,state是vis数组
static void dfs(int u, int sum, int state) {
if (sum + (n - u) < m) return;//就是n-u就是剩余还没有选的数字的数量,
// sum+(n-u)<m就是剩余的数字都选上,也不够m个数字,所以剪枝
if (sum == m) {//选了m个就输出
for (int i = 0; i < n; i++) {
if (((state >> i) & 1) == 1)
System.out.print(i + 1 + " ");
}
System.out.println();
return;
}
if (u == n) return;//所有数字都选完了
dfs(u + 1, sum + 1, state | (1 << u));//能选就先选,保持字典序!!!
dfs(u + 1, sum, state);//选不选第u个数
}
}
package 递归;
/**
* AcWing 95. 费解的开关
* <p>
* 题目描述
* 你玩过拉灯游戏吗25盏灯排成一个5x5的方形每一个灯都有一个开关游戏者可以改变它的状态每一步游戏者可以改变某一个灯的状态游戏者改变一个灯的状态会产生连锁反应和这个灯上下左右相邻的灯也要相应地改变其状态
* <p>
* 我们用数字1表示一盏开着的灯用数字0表示关着的灯下面这种状态
* <p>
* 10111
* 01101
* 10111
* 10000
* 11011
* 在改变了最左上角的灯的状态后将变成
* <p>
* 01111
* 11101
* 10111
* 10000
* 11011
* 再改变它正中间的灯后状态将变成
* <p>
* 01111
* 11001
* 11001
* 10100
* 11011
* 给定一些游戏的初始状态编写程序判断游戏者是否可能在6步以内使所有的灯都变亮
* 输入格式
* 第一行输入正整数n代表数据中共有n个待解决的游戏初始状态
* 以下若干行数据分为n组每组数据有5行每行5个字符每组数据描述了一个游戏的初始状态各组数据间用一个空行分隔
* 输出格式
* 一共输出n行数据每行有一个小于等于6的整数它表示对于输入数据中对应的游戏状态最少需要几步才能使所有灯变亮
* 对于某一个游戏初始状态若6步以内无法使所有灯变亮则输出-1”。
* 数据范围
* 0<n500
* 输入样例
* 3
* 00111
* 01011
* 10001
* 11010
* 11100
* <p>
* 11101
* 11101
* 11110
* 11111
* 11111
* <p>
* 01111
* 11111
* 11111
* 11111
* 11111
* 输出样例
* 3
* 2
* -1
*/
public class 费解的开关 {
public static void main(String[] args) {
}
static int[][] dirs = {{0, 0}, {0, 1}, {1, 0}, {0, -1}, {-1, 0}};
static char[][] g = new char[10][10];
static void turn(int x, int y) {
for (int i = 0; i < 5; i++) {
int nx = x + dirs[i][0], ny = y + dirs[i][1];
if (nx >= 0 && nx < 5 && ny >= 0 && ny < 5) {
g[nx][ny] ^= 1;
}
}
}
static void work() {
for (int k = 0; k < 1 << 5; k++) {
char[][] backup = new char[10][10];
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 10; j++) {
backup[i][j] = g[i][j];
}
}
for (int j = 0; j < 5; j++) {
}
}
}
}
package 递归;
import java.util.Scanner;
import static java.lang.System.in;
/**
* 92. 递归实现指数型枚举
* 从 1~n 这 n 个整数中随机选取任意多个,输出所有可能的选择方案。
* 输入格式
* 输入一个整数n。
* 输出格式
* 每行输出一种方案。
* 同一行内的数必须升序排列,相邻两个数用恰好1个空格隔开。
* 对于没有选任何数的方案,输出空行。
* 本题有自定义校验器(SPJ),各行(不同方案)之间的顺序任意。
* 数据范围
* 1≤n≤15
* 输入样例:
* 3
* 输出样例:
* 3
* 2
* 2 3
* 1
* 1 3
* 1 2
* 1 2 3
*/
public class 随机选数 {
public static void main(String[] args) {
Scanner sc = new Scanner(in);
n = sc.nextInt();
dfs(0,0);
}
static int n;
static void dfs(int u, int state) {
if (u == n) {//经过所有的数
for (int i = 0; i < n; i++) {
if (((state >> i) & 1) == 1)//为1说明用这个数
System.out.print(i + 1+" ");//枚举的0~(n-1)所以i+1
}
System.out.println();
return;
}
dfs(u + 1, state);//不用第u个数字
dfs(u + 1, state | (1 << u));//用第u个数字,把state的第u位变成为1
}
}
package search;
import java.util.Scanner;
import static java.lang.System.in;
public class ZJU1002放碉堡 {
private static int n;
private static char[][] arr = new char[4][4];
public static void main(String[] args) {
Scanner sc = new Scanner(in);
while (true) {
n = sc.nextInt();
if (n == 0) break;
ibest=0;
for (int i = 0; i < n; i++) {
String z = sc.next();
for (int j = 0; j < n; j++) {
arr[i][j] = z.charAt(j);
}
}
dfs(0, 0);
System.out.println(ibest);
}
}
static int ibest = 0;
static void dfs(int k, int cur) {
int x, y;
if (k == n * n) {
if (cur > ibest) {
ibest = cur;
}
return;
} else {
x = k / n;
y = k % n;
if (arr[x][y] == '.' && canPut(x, y)) {
arr[x][y] = 'O';
dfs(k + 1, cur + 1);
arr[x][y] = '.';
}
dfs(k + 1, cur);
}
}
static boolean canPut(int row, int col) {
int i = 0;
//判断列合法性
for (i = row - 1; i >= 0; i--) {
if (arr[i][col] == 'O') return false;//O代表有碉堡
if (arr[i][col] == 'X') break;
}
//判断行合法性
for (i = col - 1; i >= 0; i--) {
if (arr[row][i] == 'O') return false;
if (arr[row][i] == 'X') break;
}
return true;
}
}
package search;
import java.util.Scanner;
/**
* 5 1
* 5 1 3
* 5 1 2
* 5 1 1
* 5 1 3 1
* 5 1 3 1 1
* 5 2 1
* 5 2
* 5 2 2
* 5 3 1
* 5 3 1 2
* 5 3
* 5 4
* 5 5
*/
public class 序列计数 {
static Scanner sc = new Scanner(System.in);
public static void main(String[] args) {
long s = System.nanoTime();
int n = 1000;
int ans[][] = new int[n + 1][n + 1];
int jg = 0;
for (int i = 1; i <= n; i++) {
jg += jie(ans, n, i);
jg %= 10000;
}
System.out.println(jg % 10000);
long t = System.nanoTime();
System.out.println((t - s) / 1e9);
}
static int[] c = new int[1005];
private static int jie(int[][] ans, int n, int m) {
if (Math.abs(n - m) <= 1) return 1;
if (ans[n][m] != 0) {
return ans[n][m];
}
int te = 1;
for (int i = 1; i < Math.abs(n - m); i++) {
te = (te + jie(ans, m, i)) % 10000;
}
return ans[n][m] = te;
}
static int st(int n, int m) {
return 0;
}
}
package search;
import java.util.*;
import static java.lang.System.in;
public class 节目 {
static class node {
int sum, index;
public node(int sum, int index) {
this.sum = sum;
this.index = index;
}
}
static node[] node;
public static void main(String[] args) {
Scanner sc = new Scanner(in);
n = sc.nextInt();
m = sc.nextInt();
node = new node[n];
for (int i = 0; i < n; i++) {
node[i] = new node(sc.nextInt(), i);
}
Arrays.sort(node, 0, node.length, new Comparator<节目.node>() {
@Override
public int compare(节目.node node, 节目.node t1) {
return t1.sum - node.sum;
}
});
Arrays.sort(node, 0, m , new Comparator<node>() {
@Override
public int compare(节目.node node, 节目.node t1) {
return node.index - t1.index;
}
});
for (int i = 0; i < m; i++) {
System.out.println(node[i].sum);
}
}
static int n, m;
}
package search;
import java.util.ArrayList;
import java.util.Scanner;
import static java.lang.System.in;
/**
* 一个地方可能长多次草
*/
public class 长草 {
public static void main(String[] args) {
Scanner sc = new Scanner(in);
n = sc.nextInt();
m = sc.nextInt();
arr = new char[n][m];
String s;
ArrayList<Integer> l = new ArrayList<Integer>();
for (int i = 0; i < n; i++) {
s = sc.next();
for (int j = 0; j < m; j++) {
arr[i][j] = s.charAt(j);
if (arr[i][j] == 'g')
l.add(i * m + j);
}
}
k = sc.nextInt();
int nnx, nny;
for (Integer w : l) {
nnx = w / m;
nny = w % m;
dfs(nnx, nny, k);
}
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
System.out.print(arr[i][j] + " ");
}
System.out.println();
}
}
static int n, m, k;
static char[][] arr;
static int[][] dirs = {{0, 1}, {1, 0}, {-1, 0}, {0, -1}};
static int nx, ny;
static void dfs(int x, int y, int t) {
if (t < 0) return;
arr[x][y] = 'g';//长草
for (int d = 0; d < 4; d++) {
nx = x + dirs[d][0];
ny = y + dirs[d][1];
if (inArea(nx, ny)) {
dfs(nx, ny, t - 1);
}
}
}
static boolean inArea(int x, int y) {
return x >= 0 && x < n && y >= 0 && y < m;
}
}
package 大整数运算技巧;
import java.math.BigInteger;
public class ZJU火星算数1205 {
public static void main(String[] args) {
System.out.println(vs(10, 10));
}
public static String vs(int a, int b) {
BigInteger c = new BigInteger(String.valueOf(a));
BigInteger d = new BigInteger(String.valueOf(b));
BigInteger add = c.add(d);
add.toString(10);
return add.toString() ;
}
}
package graph;
package dp;
import java.util.ArrayList;
import java.util.Arrays;
/**
......@@ -13,14 +14,11 @@ import java.util.Arrays;
*/
public class LIS {
public static void main(String[] args) {
// int[] arr = {4, 2, 3, 1, 5, 2, 6};
int i=1;
System.out.println(-i);
// for (int i = 0; i < 1000000; i++) {
// int[] arr = random(200);
// if (dpBest(arr) != dp(arr, arr.length))
// System.out.println("no");
// }
for (int i = 0; i < 1000000; i++) {
int[] arr = random(200);
if (dpBest(arr) != dp(arr, arr.length))
System.out.println("no");
}
}
......@@ -37,6 +35,7 @@ public class LIS {
/**
* O(N logN)最优实现,LeetCode官方题解非常牛逼
* dp[i] 代表长度为i的最长上升子序列末尾的那个元素(数字)
*
* @param nums
* @return
......
package graph;
package dp;
/**
* 假设你正在爬楼梯。需要 n 阶你才能到达楼顶。
......
package graph;
package dp;
/**
* 给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。
......
package graph;
package dp;
import java.util.Arrays;
import java.util.Scanner;
......
package graph;
package dp;
/**
* https://mp.weixin.qq.com/s?__biz=MzUyNjQxNjYyMg==&mid=2247486923&idx=2&sn=6c1c8aeb4db68522e67ddf8c1e933660&chksm=fa0e624acd79eb5cdb410808921609a830b9b9221e813e4eb89cf551ca48f317668d44b095d2&scene=21#wechat_redirect
......
package graph;
package dp;
import java.util.ArrayList;
import java.util.Collections;
......
package graph;
package dp;
import java.util.Arrays;
import java.util.Scanner;
......
###位运算
###数学
````
在处理整数可以对数值进行位运算
01010110
......@@ -7,6 +7,10 @@
>>>无符号右移,用0填充高位
>>右移使用符号位填充高位
没有无符号左移操作
1 << n 相当于求2^n
n >> x 相当于n/2^x
对于int型,1>>35与1>>3是相同的,因为int只有32位,取模35%32=3所以结果相同
a b ~a a&b a|b a^b
1 1 0 1 1 0
......@@ -16,6 +20,13 @@ a b ~a a&b a|b a^b
与:都为1结果才为1
或:有一个为1结果为1
异或:二者不同时结果为1
正数表示二进制,就是直接转换成二进制
负数表示二进制:补码=1+反码=1+(~x+1)
x的负数表示~x+1也可以直接-x
~x+1+x=0
用加法实现减法,所以使用补码来表示负数
````
###位运算的技巧
```
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册