1,巧用进制
变种3进制
solution:
如二进制:
1011 为11 表示:取 不取 取 取。
将其运用到三进制中即可
package 学习哔哩哔哩;
//2021年4月1日上午8:58:47
//writer:apple
import java.util.*;
import java.io.*;
public class 变种3进制 {
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner s=new Scanner(System.in);
int n=s.nextInt();
String n3=Integer.toString(n, 3);//转成三进制,用字符保存
char b[]=new StringBuilder(n3).reverse().toString().toCharArray();//进行翻转 成为升序
List<Integer> ans=new ArrayList<>();
for(int i=0;i<b.length;i++)
{
if(b[i]=='2')
{
ans.add(-1);
if(i==b.length-1)
{
ans.add(1);
}
else b[i+1]++;
}
else if(b[i]=='3')
{
ans.add(0);
if(i==b.length-1)
{
ans.add(1);
}
else b[i+1]++;
}
else {//为1 和0
ans.add(b[i]-'0');
}
}
for(int i=0;i<ans.size();i++)
{
int a=(int) (ans.get(i)*Math.pow(3,ans.size()-i-1));
System.out.print(a+" ");
}
}
}
2,Nim游戏
是一个最后取物品为胜者的游戏。()
Alice先手。Bob后手
solution:
对每堆石子做异或运算。
结果非0,先手胜(Alice获胜,因为他先手可以让局面变成0)
结果为0,后手胜。
public class Nim {
static int n;
static int a[];
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner s=new Scanner(System.in);
n=s.nextInt();
a=new int[n];
for(int i=0;i<n;i++)
{
a[i]=s.nextInt();
}
int ans=solve();
if(ans>0) System.out.println("Alice");
else System.out.println("Bob");
}
private static int solve() {
// TODO Auto-generated method stub
int res=0;
for(int i=0;i<n;i++)
{
res^=a[i];
}
return res;
}
}
阶梯Nim博弈:POJ1704
//2021年4月1日下午6:05:01
//writer:apple
import java.util.*;
import java.io.*;
public class Main{
static int n;
static int a[];
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner s=new Scanner(System.in);
n=s.nextInt();
for(int i=0;i<n;i++)
{
int nn=s.nextInt();
a=new int[nn];
for(int j=0;j<nn;j++)
{
a[j]=s.nextInt();
}
boolean ans=solve();
if(ans) System.out.println("Georgia will win");//先手赢
else System.out.println("Bob will win");
}
}
private static boolean solve() {
// TODO Auto-generated method stub
int len=a.length;
int res=0;
Arrays.sort(a);
if((len&1)==1)
{
for(int i=0;i<len;i=i+2)
{
if(i==0)
{
res^=(a[i]-1);
}
else {
res^=(a[i]-a[i-1]-1);
}
}
}
else {
for(int i=1;i<len;i=i+2)
{
res^=(a[i]-a[i-1]-1);
}
}
return res==0?false:true;
}
}
取球博弈
两个人玩取球的游戏。
一共有N个球,每人轮流取球,每次可取集合{n1,n2,n3}中的任何一个数目。
如果无法继续取球,则游戏结束。
此时,持有奇数个球的一方获胜。
如果两人都是奇数,则为平局。
假设双方都采用最聪明的取法,
第一个取球的人一定能赢吗?
试编程解决这个问题。
输入格式:
第一行3个正整数n1 n2 n3,空格分开,表示每次可取的数目 (0<n1,n2,n3<100)
第二行5个正整数x1 x2 … x5,空格分开,表示5局的初始球数(0<xi<1000)
输出格式:
一行5个字符,空格分开。分别表示每局先取球的人能否获胜。
能获胜则输出+,
次之,如有办法逼平对手,输出0,
无论如何都会输,则输出-
例如,输入:
1 2 3
1 2 3 4 5
程序应该输出:
- 0 + 0 -
再例如,输入:
1 4 5
10 11 12 13 15
程序应该输出:
0 - 0 + +
再例如,输入:
2 3 5
7 8 9 10 11
程序应该输出:
- 0 0 0 0
资源约定:
峰值内存消耗(含虚拟机) < 256M
CPU消耗 < 3000ms
package 第七届;
//2021年4月5日下午10:29:42
//writer:apple
import java.io.*;
import java.util.*;
import java.math.*;
public class 取球博弈 {
static int a[]=new int[3];
static int x[]=new int[5];
static char ans[]=new char[5];
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner s=new Scanner(System.in);
//while(s.hasNext())
//{
for(int i=0;i<3;i++) a[i]=s.nextInt();
for(int i=0;i<5;i++) x[i]=s.nextInt();
StringBuilder ans=new StringBuilder();
for(int i=0;i<5;i++)
{
int ann=f(x[i],0,0,true);
if(ann==2) ans.append("+ ");
else if(ann==1) ans.append("0 ");
else ans.append("- ");
}
System.out.println(ans.toString());
//}
}
private static int f(int N, int me, int he, boolean isme) {
// TODO Auto-generated method stub
int mina=a[0];
for(int i=0;i<3;i++) mina=Math.min(mina,a[i]);
if(N<mina)
{
if((me&1)==1&&(he&1)!=1) return 2;
else if((me&1)!=1&&(he&1)==1) return 0;
else return 1;
}
if(isme)
{
int max=0;
for(int i=0;i<3;i++)
{
if(N>=a[i])
max=Math.max(max,f(N-a[i],me+a[i],he,false));
}
return max;
}
else {
int min=2;
for(int i=0;i<3;i++)
{
if(N>=a[i])
min=Math.min(min,f(N-a[i],me,he+a[i],true));
}
return min;
}
}
}
3,必备求和公式
4,欧几里得算法及其扩展
欧几里得算法就是辗转相除法
public statici int gcd(int m,int n)
{
if(n==0)return m;
return gcd(n,m%n);
}
贝祖等式:
5,模运算
求余为取模。
(a+b)%m==(a%m+b%m)%m
(ab)%m==(a%mb)%m 但不等于(a%m)*(b%m)
6,素数
考察质因数:
判断是否是素数
public static boolean isprime(int x)
{
if(x==1) return false;
for(int i=2;i<=Math.sqrt(x);i++)
{
if(x%i==0) return false;
}
return true;
}
分解质因数
public class 分解质因数 {
static int n;
static Map<Integer,Integer> m=new HashMap<>();//存放质因数和对应次数
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner s=new Scanner(System.in);
n=s.nextInt();
solve(n);
StringBuilder sb=new StringBuilder();
for(Map.Entry<Integer, Integer> entry:m.entrySet())
{
int k=entry.getKey();
int v=entry.getValue();
while(v-->0)
{
sb.append("*"+k);
}
}
System.out.println(sb.substring(1));
}
public static boolean isprime(int x)
{
if(x==1) return false;
for(int i=2;i<=Math.sqrt(x);i++)
{
if(x%i==0) return false;
}
return true;
}
private static void solve(int n) {
// TODO Auto-generated method stub
for(int i=2;i<=Math.sqrt(n);i++)
{
while(isprime(i)&&n%i==0)
{
Integer val=m.get(i);
if(val==null)
{
m.put(i, 1);
}
else m.put(i,val+1);
n/=i;
}
}
}
}
7,求解对数
Math.log(x):以e为底 x的对数
Math.log(x)/Math.log(d):以d为底 x的对数
8,素数定理
从不大于n的自然数随机选一个,它是素数的概率大约是1/(lnn)
意思就是:在1-x中的素数个数约为:x/(lnx)个
求解第n个素数:
1,运用素数定理,确定这个素数的范围
2,大到小求解
import java.util.*;
public class 求第x个素数 {
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner s=new Scanner(System.in);
int n=s.nextInt();
int maxx=sushudingli(n);//所以第n个素数在[2,maxx]中找
while(true)
{
if(isprime(maxx)) break;
maxx--;
}
System.out.println(maxx);
}
private static int sushudingli(int n) {
// TODO Auto-generated method stub
int x=2;
while(x/Math.log(x)<n)
{
x++;
}
return x;
}
public static boolean isprime(int x)
{
if(x==1) return false;
for(int i=2;i<=Math.sqrt(x);i++)
{
if(x%i==0) return false;
}
return true;
}
}
9,快速幂运算
private static int poww(int i, int j) {
// TODO Auto-generated method stub
int ans=1;
while(j!=0)
{
if((j&1)==1)
{
ans*=i;
}
i=i*i;
j>>=1;
}
return ans;
}
10,矩阵快速幂
两矩阵能相乘要求:第一个col等于第二个row。
适用于求解有递推公式的f(n),如第n个斐波那契数
解法和快速幂一样。
求某矩阵的n次方
import java.io.*;
import java.util.*;
public class 矩阵快速幂 {
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner s=new Scanner(System.in);
int hl=s.nextInt(); int ci=s.nextInt();//求矩阵的ci次方
int rec[][]=new int[hl][hl];
for(int i=0;i<hl;i++)
{
for(int j=0;j<hl;j++) rec[i][j]=s.nextInt();
}
int ans[][]=recpow(rec,ci);
for(int i=0;i<hl;i++)
{
for(int j=0;j<hl;j++)
{
System.out.print(ans[i][j]+" ");
}
System.out.println();
}
}
private static int[][] recpow(int[][] rec, int ci) {
// TODO Auto-generated method stub
int len=rec.length;
int ans[][]=new int[len][len];
//初始为 1 0 0
// 0 1 0
// 0 0 1
for(int i=0;i<len;i++)
ans[i][i]=1;
while(ci!=0)
{
if((ci&1)==1)
ans=mul(ans,rec);
rec=mul(rec,rec);
ci>>=1;
}
return ans;
}
private static int[][] mul(int[][] ans, int[][] rec) {
// TODO Auto-generated method stub
//这里只考虑ans和rec两矩阵 长宽相同
int len=ans.length;
int Ans[][]=new int[len][len];
for(int i=0;i<len;i++)
{
for(int j=0;j<len;j++)
{
for(int k=0;k<len;k++)
{
Ans[i][j]+=ans[i][k]*rec[k][j];
}
}
}
return Ans;
}
}
11 ,欧拉定理:
欧拉定理中包含一个欧拉函数:
n的欧拉函数是:1-n中与n互质的个数
12:三角形公式: