4. +
SourceCode
class Execution {
private int[] primeList;
private long[] resultSet;
public Execution(int limit) {
primeList = new Prime(limit).getPrimPrimeList();
calculation();
}
private void calculation() {
resultSet = new long[primeList.length - 1];
IntStream.range(0, resultSet.length).parallel().forEach(
e -> resultSet[e] = calcB(primeList[e], primeList[e + 1]));
}
private long calcB(int p1, int p2) {
int mask = (int) Math.pow(10, count(p1));
for (long i = p2; i < Long.MAX_VALUE; i += p2) {
if (i % mask == p1) {
return i;
}
}
return -1;
}
private int count(int n) {
int c = 0;
while (n != 0) {
n /= 10;
c++;
}
return c;
}
public long getSum() {
long s = 0;
for (long n : resultSet) {
if (n == -1) {
System.out.println("!!!!!!!!!");
}
s += n;
}
return s;
}
}
5. +
class Prime {
private boolean[] primeBool;
public Prime(int limit) {
primeBool = new boolean[limit];
calculation();
}
private void calculation() {
Arrays.fill(primeBool, true);
primeBool[0] = false;
primeBool[1] = false;
for (int i = 2; i < primeBool.length; i++) {
if (primeBool[i]) {
for (int j = i + i; j < primeBool.length; j += i)
primeBool[j] = false;
}
}
}
public ArrayList<Integer> getPrimeList() {
ArrayList<Integer> ret = new ArrayList<>();
for (int i = 0; i < primeBool.length; i++) {
if (primeBool[i] && (5 <= i)) {
ret.add(i);
}
}
return ret;
}
public int[] getPrimPrimeList() {
ArrayList<Integer> tmp = getPrimeList();
int[] ret = new int[tmp.size()];
for (int i = 0; i < ret.length; i++) {
ret[i] = tmp.get(i);
}
return ret;
}}
8. +class GPUExecution extends Kernel {
private int[] primeList;
private long[] resultSet;
public GPUExecution(int limit) {
primeList = new Prime(limit).getPrimPrimeList();
resultSet = new long[primeList.length - 1];
}
public void run() {
int index = getGlobalId();
resultSet[index] = calcB(primeList[index], primeList[index + 1]);
}
private long calcB(int p1, int p2) {
int mask = (int) Math.pow(10, count(p1));
for (long i = p2; i < Long.MAX_VALUE; i += p2) {
if (i % mask == p1) {
return i;
}
}
return -1;
}
9. + private int count(int n) {
int c = 0;
while (n != 0) {
n /= 10;
c++;
}
return c;
}
public long getSum() {
long s = 0;
for (long n : resultSet) {
if (n == -1) {
System.out.println("!!!!!!!!!");
}
s += n;
}
return s;
}
public int getExecuteSize() {
return resultSet.length;
}
}
GPUExecution gpuExecution = new GPUExecution(1000010);
gpuExecution.execute(gpuExecution.getExecuteSize());
System.out.println(gpuExecution.getSum());
呼び出し元
10. +
速いアルゴリズム
class FastExecution {
private int[] primeList;
private long[] resultSet;
public FastExecution(int limit) {
primeList = new Prime(limit).getPrimPrimeList();
resultSet = new long[primeList.length];
calculation();
}
private void calculation() {
IntStream.range(0, resultSet.length - 1).parallel().forEach(e -> {
long p1 = primeList[e];
long p2 = primeList[e + 1];
long a = DigitCountFactor(p1);
long b = p2 - p1;
long n = p2;
long[] rs = extended_gcd(a, n);
long x = rs[0] * b % n;
if (x < 0) {
x = n + x;
resultSet[e] = x * a + p1;
}); }
11. +
private long DigitCountFactor(long number) {
long factor = 1;
while (number > 0) {
factor *= 10;
number /= 10;
}
return factor;
}
private long[] extended_gcd(long a, long b) {
long x = 0;
long lastx = 1;
long y = 1;
long lasty = 0;
while (b != 0) {
long quotient = a / b;
long temp = b;
b = a % b;
a = temp;
temp = x;
x = lastx - quotient * x;
lastx = temp;
temp = y;
y = lasty - quotient * y;
lasty = temp;
}
return new long[]{lastx, lasty, a};
}
public long getSum() {
long s = 0;
for (long n : resultSet) {
if (n == -1) {
System.out.println("!!!!!!!!!");
}
s += n;
}
return s;
}}
12. +
実行時間の比較
0 20000 40000 60000 80000 100000 120000 140000 160000
CPU
GPU
Fast
CPU GPU Fast
ELAPSEDTIME 143275 87500 877