例6【因数分解】
求两个数的最大公约数与最小公倍数
解析:关键在算数基本定理--质因数分解的唯一性
欧几里得定理:gcd(a,b) = gcd(b,a%b) ---一个数能除开 A,B, 那么一定能除开A-B A+B
最小公倍数 = 乘积 / 最大公约数
public class Main {
//greatest common divisor
static int gcd(int a,int b){
if(b==0)
return a;
return gcd(b,a%b);
}
//lowest common muultiple
static int lcm(int a,int b){
return a * b / gcd(a,b);
}
public static void main(String[] args) {
System.out.println(gcd(60,42));// 6
System.out.println(lcm(60,42));// 420
}
}
例7【一步之遥】
从昏迷中醒来,小明发现自己被关在X星球的废矿车里。
矿车停在平直的废弃的轨道上。
他的面前是两个按钮,分别写着“F”和“B”。
小明突然记起来,这两个按钮可以控制矿车在轨道上前进和后退。
按F,会前进97米。按B会后退127米。
透过昏暗的灯光,小明看到自己前方1米远正好有个监控探头。
他必须设法使得矿车正好停在摄像头的下方,才有机会争取同伴的援助。
或许,通过多次操作F和B可以办到。
矿车上的动力已经不太足,黄色的警示灯在默默闪烁...
每次进行 F 或 B 操作都会消耗一定的能量。
小明飞快地计算,至少要多少次操作,才能把矿车准确地停在前方1米远的地方。
请填写为了达成目标,最少需要操作的次数。
解析:97x + 127y = 1....不定方程的整数解
扩展欧几里得定理:
Ax + By = gcd(A,B) 必有解,求解方法:
A分解成 A/B*B+A%B =》 凑A%B
public class Main {
//解不定方程 97x+127y=1
static int e_gcd(int x,int y,int []xy) {
if(y==0){
xy[0] = 1;
xy[1] = 0;
return x;
}
int gcd = e_gcd(y,x%y,xy);
int t = xy[0];
xy[0] = xy[1];
xy[1] = t - x/y * xy[0];
return gcd;
}
public static void main(String[] args) {
int []xy = new int[2];
System.out.println(e_gcd(97,127,xy));
System.out.println("x:" + xy[0] + " y:" + xy[1]);//x:55 y:-42
}
}
例8【素数表】
第1个素数是2,第2个素数是3,...求第100002(十万零二)个素数
解析:利用素数的筛法,而关键在于数组应该开多大--素数分布密度公式
素数分布定理:不大于n的素数个数为:n / ln(n)
public static void main(String[] args) {
/* double t = 100;
while(t / Math.log(t) < 100002)
t = t * 1.1;
System.out.println(t);//N = 1515867.357380462*/
int N = 1520 * 1000;
int x = 100002;
byte[]a = new byte[N];//使用byte数组节省空间
for(int i=2;i<N/2;i++){
if(a[i] == 1)//越过已经找到的合数
continue;
for(int k=2;k<=N/i;k++)
if(i*k<N) a[i*k] = 1;
}
int sum = 0;
for(int i=2;i<N;i++){
if(a[i]==0)
sum++;
if(sum==x){
System.out.println(i);//1299743
break;
}
}
}