fbe*_*rdo 7 c algorithm math prime-factoring number-theory
在开始之前,让我说:这不是功课,只是简单,陈旧,有趣.
现在,我试图想出一个能够回答这个问题的算法1/x + 1/y = 1/n!.
正如您在上面的链接中所看到的,作者只询问提示而不是实际答案,所以我会请求同样的.
我将表达式简化为(x - n!)(y - n!)=(n!)^ 2,如其中一个答案所示,到那时我理解了(x,y)对的组合数与n!^ 2的除数数相同(如果我错了,请纠正我).
所以,正如接受的答案所暗示的那样,我试图得到每个素数组成N!^ 2的所有因子的乘法.
我在C中使用试验分区得出了一些代码来分解N!^ 2和Eratosthenes的Sieve以获得所有素数达到sqrt(N!^ 2).
现在的问题是内存,我试过N = 15而我的Mac(四核6GB内存)几乎死在我身上.问题是记忆力.所以我添加了一些printf并尝试使用N = 11:
Sieve of Eratosthenes took 13339.910000 ms and used 152 mb of memory
n= 11; n!^2 = 1593350922240000; d = 6885
[2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,5,5,5,5,7,7,11,11]
Run Code Online (Sandbox Code Playgroud)
该列表是N!^ 2的所有主要因素(当然除了1和N!^ 2).
我想要一些关于如何最小化内存消耗和可能的优化的提示.
代码吼叫,这只是一个快速实验,所以我确信它可以优化.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <strings.h>
#include <sys/time.h>
#include <assert.h>
//Linked List
struct node {
struct node * next;
long val;
};
void addValue(struct node *list, long val) {
struct node *n = list;
if (n->val == -1) {
n->val = val;
return;
}
while (n->next) {
n = n->next;
}
struct node *newNode = malloc(sizeof(struct node));
newNode->val = val;
newNode->next = NULL;
n->next = newNode;
}
void freeLinkedList(struct node *list) {
struct node *c = list;
if (!c) return;
struct node *n = c->next;
free(c);
freeLinkedList(n);
}
void printList(struct node *list) {
struct node *n = list;
printf("[");
while (n) {
printf("%ld", n->val);
n = n->next;
if (n) {
printf(",");
}
}
printf("]\n");
}
//-----------
int fac(int n) {
if (n == 1) return 1;
return fac(n-1)*n;
}
//Sieve of Eratosthenes
int sieve_primes(long limit, long **list) {
struct timeval t1;
struct timeval t2;
double elapsedTime = 0;
gettimeofday(&t1, NULL);
assert(limit > 0);
//Create a list of consecutive integers from 2 to n: (2, 3, 4, ..., n).
long arrSize = limit-1;
long *arr = malloc(sizeof(long)*arrSize);
long c = 2;
for (long i = 0; i < arrSize; i++) {
arr[i] = c++;
}
assert(arr[arrSize-1] == limit);
for (long i = 0; i < arrSize; i++) {
//Let p be equal to the first number not crossed
long p = arr[i];
if (p == 0) continue;
//Starting from p, count up in increments of p and mark each of these numbers greater than p itself in the list.
for (long f = p+p; f < arrSize; f+=p) {
arr[f] = 0;
}
}
*list = arr;
gettimeofday(&t2, NULL);
elapsedTime = (t2.tv_sec - t1.tv_sec) * 1000.0; // sec to ms
elapsedTime += (t2.tv_usec - t1.tv_usec) / 1000.0; // us to ms
printf("Sieve of Eratosthenes took %f ms and used %lu mb of memory\n",elapsedTime, (arrSize * sizeof(int))/1024/1024);
return arrSize;
}
void trial_division(struct node* list, long n) { if (n == 1) {
addValue(list, 1);
return;
}
long *primes;
long primesSize = sieve_primes(sqrt(n), &primes);
struct timeval t1;
struct timeval t2;
double elapsedTime = 0;
gettimeofday(&t1, NULL);
for (long i = 0; i < primesSize; i++) {
long p = primes[i];
if (p == 0) continue;
if (p*p > n) break;
while (n % p == 0) {
addValue(list, p);
n/=p;
}
}
if (n > 1) {
addValue(list, n);
}
free(primes);
}
int main(int argc, char *argv[]) {
struct node *linkedList = malloc(sizeof(struct node));
linkedList->val = -1;
linkedList->next = NULL;
long n = 11;
long nF = fac(n);
long nF2 = nF*nF;
trial_division(linkedList, nF2);
long multOfAllPrimeFactors = 1;
struct node *c = linkedList;
while (c) {
long sumOfVal = 2;
long val = c->val;
c = c->next;
while(c) {
long val2 = c->val;
if (val == val2) {
sumOfVal++;
c = c->next;
} else break;
}
multOfAllPrimeFactors*=sumOfVal;
}
printf("n= %ld; n!^2 = %ld; d = %ld\n", n,nF2, multOfAllPrimeFactors);
printList(linkedList);
freeLinkedList(linkedList);
}
Run Code Online (Sandbox Code Playgroud)
编辑:
作为一个例子,我将向您展示计算以获得初始方程的所有可能的正整数解:
3!^ 2 = 36 =(3 ^ 2*2 ^ 2*1 ^ 0)
因此,对于丢番图方程,存在(1 + 2)(1 + 2)(1 + 0)= 9个可能的正整数解.如果计算负整数,则加倍.我正在使用WolframAlpha.
编辑2:
我想我刚刚发现"这是一个什么因素",我得到了这个非常有趣的输出:
3! = [2,3]
3!^2 = [2,2,3,3]
3!^3 = [2,2,2,3,3,3]
3!^4 = [2,2,2,2,3,3,3,3]
Run Code Online (Sandbox Code Playgroud)
感谢:D
Mys*_*ial 11
这里的诀窍是确切地认识到因子N!是什么.这是从所有数的乘积1来N.这已经向前迈出了一大步.
所以你需要做的只是将每个数字的因子分解1为N.
从这个意义上说,你不需要筛选N!.相反,只需要筛选sqrt(N).剩下的就是合并你所有的优势因素.
更简单的是,您不需要将数字计算到N.您只需计算素因子.你可以不用担心哪些数字是因素.
让我手工做15.
最多15个,有3个倍数,2个,3个倍数,4个,1个倍数,8个,总共11个因子为2.
最多15个有5个倍数的3,一个倍数为9,总共6个因子为3.
最多15个,有3个倍数为5,总共3个因子为5.
最多15个有2个倍数的7,总共2个因子7.
11和13各有1个.
那15!= 2 11*3 6*5 3*7 2*11*13.
找到N的素因子化!你必须: