本帖最后由 jixun66 于 2020-11-9 01:31 编辑
package moe.jixun;
import java.math.BigInteger;
class BIStore {
private final Object lockValue = new Object();
private final Object lockSum = new Object();
private BigInteger sum = BigInteger.ZERO;
private BigInteger value;
BIStore(BigInteger max) {
this.value = max.add(BigInteger.ONE);
}
public BigInteger next(){
synchronized (lockValue) {
value = value.subtract(BigInteger.ONE);
return value;
}
}
public void add(BigInteger toAdd) {
synchronized (lockSum) {
this.sum = this.sum.add(toAdd);
}
}
public BigInteger getSum() {
return sum;
}
}
class ThreadRunner extends Thread {
static private final BigInteger divider = BigInteger.valueOf(10).pow(10);
private final BIStore store;
ThreadRunner(BIStore store) {
this.store = store;
}
@Override
public void run() {
for(BigInteger value = store.next(); value.compareTo(BigInteger.ZERO) > 0; value = store.next()) {
BigInteger toAdd = value.modPow(value, divider);
store.add(toAdd);
}
}
}
class AlgoMain {
private final int threadCount;
public AlgoMain(int threadCount) {
this.threadCount = threadCount;
}
static private final BigInteger divider = BigInteger.valueOf(10).pow(10);
public BigInteger f(long n) {
BIStore source = new BIStore(BigInteger.valueOf(n));
ThreadRunner[] threads = new ThreadRunner[threadCount];
for(int i = 0; i < threadCount; i++) {
threads[i] = new ThreadRunner(source);
threads[i].start();
}
for(int i = 0; i < threadCount; i++) {
try {
threads[i].join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return source.getSum();
}
private BigInteger g(long i) {
return f(i).mod(divider);
}
public void calc(long i) {
System.out.println("i = " + i);
long now = System.currentTimeMillis();
BigInteger result = this.g(i);
long delta = System.currentTimeMillis() - now;
System.out.println("g(" + i + ") = " + result + " 用时 " + delta + "ms");
}
}
public class Main {
public static void main(String[] args) {
// 线程数量
int threadCount = 2;
if (args.length > 0) {
threadCount = Integer.valueOf(args[0], 10);
}
AlgoMain inst = new AlgoMain(threadCount);
inst.calc(10);
inst.calc(1000);
inst.calc(1000000);
inst.calc((long)Math.pow(10, 10));
}
}
再来个多线程版… 以及下面不适用大数库的优化版(应该不会溢出吧)…
package moe.jixun;
class BIStore {
public static final long divider = (long) Math.pow(10, 10);
private final Object lockValue = new Object();
private final Object lockSum = new Object();
private long sum = 0L;
private long value;
BIStore(long max) {
this.value = max;
}
public long next() {
synchronized (lockValue) {
return value--;
}
}
public static long modMul(long a, long b) {
if (a == 0 || b < divider / a)
return (a * b) % divider;
long sum = 0;
while (b > 0) {
if ((b & 1) == 1) {
sum = (sum + a) % divider;
}
a = (a << 1) % divider;
b >>= 1;
}
return sum;
}
public static long selfPow(long base) throws Exception {
long exponent = base;
long result = 1L;
while (exponent > 0) {
if ((exponent & 1) == 1) {
result = BIStore.modMul(result, base);
}
exponent = exponent >> 1;
base = BIStore.modMul(base, base);
}
return result;
}
public void add(long toAdd) {
synchronized (lockSum) {
// 34 位
this.sum = (this.sum + toAdd) % divider;
}
}
public long getSum() {
return sum;
}
}
class ThreadRunner extends Thread {
private final BIStore store;
ThreadRunner(BIStore store) {
this.store = store;
}
@Override
public void run() {
for (long i = store.next(); i > 0L; i = store.next()) {
long toAdd = 0;
try {
toAdd = BIStore.selfPow(i);
} catch (Exception e) {
e.printStackTrace();
}
store.add(toAdd);
}
}
}
class AlgoMain {
private final int threadCount;
public AlgoMain(int threadCount) {
this.threadCount = threadCount;
}
public long f(long n) {
BIStore source = new BIStore(n);
ThreadRunner[] threads = new ThreadRunner[threadCount];
for (int i = 0; i < threadCount; i++) {
threads[i] = new ThreadRunner(source);
threads[i].start();
}
for (int i = 0; i < threadCount; i++) {
try {
threads[i].join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return source.getSum();
}
private long g(long i) {
return f(i) % BIStore.divider;
}
public void calc(long i) {
long now = System.currentTimeMillis();
long result = this.g(i);
long delta = System.currentTimeMillis() - now;
System.out.println("g(" + i + ") = " + result + " 用时 " + delta + "ms");
}
}
public class Main {
public static void main(String[] args) {
// 线程数量
int threadCount = 2;
if (args.length > 0) {
threadCount = Integer.valueOf(args[0], 10);
}
AlgoMain inst = new AlgoMain(threadCount);
inst.calc(10); // 405071317
inst.calc(1000); // 9110846700
inst.calc(1000000); // 4077562500
inst.calc((long)Math.pow(10, 10)); // ???
}
}
最后一问应该可以用简单地线性回归计算吧,不太懂机器学习…
import math
import numpy as np
from sklearn.linear_model import LinearRegression
# g(10) = 405071317 用时 3ms
# g(100) = 9027641920 用时 11ms
# g(1000) = 9110846700 用时 17ms
# g(10000) = 6237204500 用时 64ms
# g(100000) = 3031782500 用时 657ms
# g(1000000) = 4077562500 用时 8222ms
# g(10000000000) = 2693362500 用时 138432673ms
n = np.array([10, 100, 1000, 10000, 100000, 1000000]).reshape((-1, 1))
time = np.array([3, 11, 17, 64, 657, 8222]).reshape((-1, 1))
model = LinearRegression().fit(n, time)
# 82384373.10720266ms = 22.88 小时
print(model.predict([[math.pow(10,10)]]))
|