문제는 https://projecteuler.net/problem=108
x = n + t가 되는 t를 놓고 풀면
y = n + n*n/t가 되고, 여기서 t는 n*n의 소인수가 된다.
이를 이용하여 가능한 t를 n*n 소인수 set에서 iteration시켜 x, y를 유도하고
t가 <=n범위 안에 있을 때 count 시킨다. 그 이유는 x<=y로 놓고 식을 풀면 x <= 2*n이 나오기 때문에 t <= n을 만족해야 한다.
아래는 코드이다. 아직 110번은 못풀었다.
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <math.h>
#define P 5000
#define ECOUNT 1000
#define LAST 1260
int prime[P];
struct factor {
int *pcount;
int size;
};
bool is_prime(int n) {
int i, sqrtn = sqrt(n);
for (i = 0; prime[i] <= sqrtn && i < P; i++) {
if (n % prime[i] == 0)
return false;
}
return true;
}
void init_primes() {
int idx = 1, n = 3;
prime[0] = 2;
while (idx < P) {
if (is_prime(n)) prime[idx++] = n;
n += 2;
}
}
factor* init_factor() {
factor *f = (factor*)malloc(sizeof(factor));
int i;
f->pcount = NULL;
f->size = 0;
return f;
}
factor* factor_deep_copy(factor *f) {
factor *r = (factor*)malloc(sizeof(factor));
int i;
r->pcount = (int*)malloc(sizeof(int)*f->size);
for (i = 0; i < f->size; i++) {
r->pcount[i] = f->pcount[i];
}
r->size = f->size;
return r;
}
factor* factorize(int n) {
int i, j, fsize = 0, sqrtn = sqrt(n);
int pcount[P];
factor *f = init_factor();
for (i = 0; prime[i] <= sqrtn; i++) {
pcount[i] = 0;
while (n%prime[i] == 0) {
pcount[i]++;
n /= prime[i];
fsize = i + 1;
}
}
if (n > 1) f->size = -1;
else {
f->pcount = (int*)malloc(sizeof(int)*fsize);
for (j = 0; j < fsize; j++) f->pcount[j] = pcount[j];
f->size = fsize;
}
return f;
}
void factor_square(factor *f) {
int i;
for (i = 0; i < f->size; i++) {
f->pcount[i] *= 2;
}
}
bool is_factor_empty(factor *f) {
int i;
if (f->size == 0) return true;
for (i = 0; i < f->size; i++) {
if (f->pcount[i] > 0) return false;
}
return true;
}
int factor_to_int(factor *f) {
int n = 1, i, j;
for (i = 0; i < f->size; i++) {
for (j = 0; j < f->pcount[i]; j++) {
n *= prime[i];
}
}
return n;
}
int factor_count(factor *f) {
int cnt = 1, i;
for (i = 0; i < f->size; i++) {
cnt *= f->pcount[i] + 1;
}
return cnt;
}
bool factor_greater(factor *f, factor *g) {
// if needed, this function can be enhanced
return factor_to_int(f) > factor_to_int(g);
}
bool factor_iter_next(factor *f, factor *start) {
int i;
if (is_factor_empty(f)) return false;
for (i = 0; i < f->size; i++) {
if (f->pcount[i] > 0) {
f->pcount[i]--;
break;
}
else {
f->pcount[i] = start->pcount[i];
}
}
return true;
}
void factor_print(factor *f) {
int i;
printf("f->size = %d\n", f->size);
for (i = 0; i < f->size; i++) {
printf("%4d", f->pcount[i]);
}
printf("\n");
}
void free_factor(factor *f) {
free(f->pcount);
free(f);
}
void main() {
int i, j, tcount;
int n = LAST - 1, x, y, t;
int count = 0;
int max = 0, fmax = 0;
factor *fn, *ffn, *ff;
init_primes();
/*
for (t = 1; t <= n; t++) {
if (n*n % t == 0) {
x = n + t;
y = n + n * n / t;
count++;
}
}
printf("n = %d, count = %d\n", n, count);
system("pause");
*/
while (true) {
n++;
count = 0;
fn = factorize(n);
ffn = factor_deep_copy(fn);
factor_square(ffn);
tcount = factor_count(ffn);
if (fmax < tcount) {
fmax = tcount;
printf("n = %d, factor_count = %d\n", n, fmax);
}
if (tcount < ECOUNT) {
free_factor(fn);
free_factor(ffn);
continue;
}
count = tcount - 1;
ff = factor_deep_copy(ffn);
while (factor_iter_next(ff, ffn)) {
if (factor_greater(ff, fn)) {
count--;
}
}
free_factor(ffn);
free_factor(fn);
free_factor(ff);
if (count > ECOUNT) {
break;
}
}
printf("n = %d, count = %d\n", n, count);
system("pause");
}'Project Euler' 카테고리의 다른 글
| Project Euler #58 (Spiral primes) (0) | 2016.09.27 |
|---|---|
| Project Euler #55 (Lychrel numbers) (0) | 2016.09.19 |
| Project Euler #105 (Special subset sums: testing) (0) | 2016.09.09 |
| Project Euler #106 (Special subset sums: meta-testing) (0) | 2016.09.09 |
| Project Euler #103 (Special subset sums: optimum) (0) | 2016.09.09 |
댓글