1.容斥原理(能被整除的数)
import java.util.*;
public class Main{
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int m = sc.nextInt();
int[] p = new int[m];
for(int i = 0; i < m; i ++){
p[i] = sc.nextInt();
}
int res = 0;//记录答案
//容斥原理
for(int i = 1; i < 1 << m; i ++){//一共有2^m-1种取法
long t = 1;//记录当前循环中质数的乘积
int cnt = 0;//记录质数的个数,用来判断加减
for(int j = 0; j < m; j ++){//一共m个质数
if((i >> j & 1) == 1){//用位运算来判断当前质数是否取到
cnt ++;//个数加1
if(t * p[j] > n){//如果质数乘积大于n,也就是说n/t=0,就没有意义,结束本次循环
t = -1;
break;
}
t *= p[j];//否则把质数相乘
}
}
if(t != -1){
if(cnt % 2 == 0){
res -= n / t;//质数个数为偶数,要减去
}else{
res += n / t;//个数为奇数,要加上
}
}
}
System.out.print(res);
}
}
2.博弈论
891. Nim游戏 - AcWing题库
import java.util.*;
public class Main{
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int res = 0;
while(n -- > 0){
int x = sc.nextInt();
res ^= x;
}
if(res == 0) System.out.print("No");
else System.out.print("Yes");
}
}
892. 台阶-Nim游戏 - AcWing题库
import java.util.*;
public class Main{
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int res = 0;
for(int i = 1; i <= n; i ++){
int x = sc.nextInt();
if(i % 2 != 0) res ^= x;//只需要异或奇数台阶就可以
}
if(res == 0) System.out.print("No");
else System.out.print("Yes");
}
}
893. 集合-Nim游戏 - AcWing题库
import java.util.*;
public class Main{
static int N = 110, M = 10010, k, n;
static int[] s = new int[M];
static int[] f = new int[M];
public static int sg(int x){
if(f[x] != -1) return f[x];
Set<Integer> set = new HashSet<>();//每次建立一个新的set
for(int i = 0; i < k; i ++){
if(x >= s[i]) set.add(sg(x - s[i]));//一直递归到末尾
}
for(int i = 0; ; i ++){
if(!set.contains(i)) return f[x] = i;//从0开始判断set中有没有
}
}
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
k = sc.nextInt();
Arrays.fill(f, -1);
int res = 0;
for(int i = 0; i < k; i ++){
s[i] = sc.nextInt();
}
n = sc.nextInt();
for(int i = 0; i < n; i ++){
int x = sc.nextInt();
res ^= sg(x);//res与每个sg异或
}
if(res == 0) System.out.print("No");
else System.out.print("Yes");
}
}
894. 拆分-Nim游戏 - AcWing题库
sg函数的重要定理 求两堆数的sg(i,j) = sg(i) ^ sg(j);
import java.util.*;
public class Main{
static int[] f = new int[110];
public static int sg(int x){
if(f[x] != -1) return f[x];
Set<Integer> set = new HashSet<>();
for(int i = 0; i < x; i ++){
for(int j = 0; j <= i; j ++){
set.add(sg(i) ^ sg(j)); //sg的重要定理 求两堆数的sg(i,j) = sg(i) ^ sg(j);
}
}
for(int i = 0; ; i ++){
if(!set.contains(i)) return f[x] = i;
}
}
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
Arrays.fill(f, -1);
int res = 0;
while(n -- > 0){
int x = sc.nextInt();
res ^= sg(x);
}
if(res == 0) System.out.print("No");
else System.out.print("Yes");
}
}