비밀번호486 (PASS486) 도움 요청드립니다. gloryof11 다시 질문방을 찾게 되었습니다;; 소인수분해를 하면 약수의 갯수를 찾을 수 있을것 같아서 아래와 같이 프로그래밍을 했습니다. 동작상 이상이 없는것 처럼 보이는데 2가지 문제가 있습니다;; 1) 예제 입력의 3번째, 200 1000000 2000000 의 답이 19 가 아닌 12가 나옴 2) 시간초과 발생 혹시 제가 생각을 잘못하고 만든 코드 인지 답답하여, 문제 해결하신 분들과 고수님들 에게 조언을 부탁드립니다;; [[비밀번호 486|problem:PASS486]] #include <stdio.h> #include <time.h> int TC; unsigned long num,lo,hi; unsigned long cnt; unsigned long idx; unsigned long ARR[25]; // 2^24 = 16,777,216 , so 25 is enough as max idx. unsigned long pivot; unsigned long prime_factor; unsigned long result; int main(void) { scanf("%d",&TC); for(int i=0;i<TC;i++) { scanf("%lu %lu %lu",&num,&lo,&hi); clock_t start = clock(); for(unsigned long j=lo;j<=hi;j++) { // init pivot = prime_factor = j; idx = 0; for(unsigned long m=0;m<25;m++) ARR[m] = 0; // find prime factor for(unsigned long n=2;n<=pivot;n++) { if(prime_factor%n==0) { ARR[idx] = n; idx++; prime_factor = prime_factor/n; n = 1; pivot = prime_factor; } else { if(pivot/n+1 < n) continue; // bug fix pivot = pivot/n+1; } } // add last prime factor. upper code does not add last prime factor... ; bug fix if(prime_factor != 1) { ARR[idx] = prime_factor; idx++; } #if 0 // for debugging if(idx == 1) { printf("소수\n"); cnt = 2; } else { for(int l=0;l<idx;l++) { printf("%d ",ARR[l]); } printf("\n"); } #endif // count all divisors // 1. sort for(unsigned long k=0;k<idx;k++) { unsigned long temp = 0; for(unsigned long k2=k;k2<idx;k2++) { if(ARR[k]>ARR[k2]) { temp = ARR[k]; ARR[k] = ARR[k2]; ARR[k2] = temp; } } } // 2. sum of each prime factor * num unsigned long val = ARR[0]; unsigned long each_cnt = 1; cnt = 1; for(unsigned long k3=1;k3<=idx;k3++) { if(val == ARR[k3]) { each_cnt++; } else { cnt = cnt * (each_cnt+1); val = ARR[k3]; each_cnt = 1; } } if(cnt == num) result++; } printf("%lu\n",result); printf("time : %d\n",clock()-start); result = 0; } return 0; } 12년 전
9개의 댓글이 있습니다. hyunhwan 소인수 분해를 하는 코드에서 $n$으로 나눠지지 않을 경우 $pivot=pivot/n+1$을 하시는데 이건 어떤 의도로 넣으신거죠? 12년 전 link gloryof11 특정수가 약수를 찾을때, a 라는 수가 소수인경우,1~a 까지 모두 계산하면 시간이 많이 걸릴것 같아 연산횟수를 줄여보고자 그렇게 하였습니다. 3으로 나눠지지 않으면, a/3 ~ a 사이의 어떤수도 약수가 되지 않을 것 같다고 생각했습니다. 12년 전 link Being n이 2, 3, 4로 나누어지지 않는다면 n/24~n 사이에는 어떤 약수도 없나요? 12년 전 link gloryof11 의미가 좀 잘못 전달 된 것 같습니다. 다시 말씀드리면, n 이 2,3,4 로 나누어지지 않는다면, n/24(초과) ~ n(미만) 사이의 어떠한 수도 n 의 약수가 되지 못한다고 생각했습니다. (만약 약수가 있으면, 2,3,4 중 하나도 약수여야 하니까요.) 12년 전 link Being 네 제가 맞게 이해한 것 같은데요.. 그래서 n = 25면 (25/24, 25) 사이의 어떤 수도 n의 약수가 아니라 보신 것 아닌가요? 12년 전 link hyunhwan 그리고$n$ 소인수분해 할때도 반복문을 $2$부터 $\sqrt{n}$ 만큼만 돌려도 됩니다. 12년 전 link gloryof11 (Dear Being 님) n=25 인경우, 아래와같이 동작합니다. 1. 2 는 약수아님. 그러므로 pivot = 25/2+1 = 13 2. 3 은 약수아님. 그러므로 pivot = 25/3+1 = 9 3. 4 는 약수아님. 그러므로 pivot = 25/4+1 = 7 4. 5 는 약수임. (찾았다!) (제가 설명을 잘못드렸습니다;; pivot 은 항상 n 을 기준으로 변경이 되어야 합니다. 시간내어 관심 가져주셔서 감사드립니다!) 12년 전 link kcm1700 설명하신대로 작동하려면 pivot = pivot/n+1;이 아니라 pivot = j/n+1;이 되어야겠죠. 결국 $\sqrt{j}$까지 돌리는 것을 의도하신 것 같은데 pivot 없이 그냥 조건문을 n <= j/n으로 해주시면 됩니다. 12년 전 link gloryof11 pivot 이라는 변수를 부가적으로 사용하면서, 어려운 방법으로 소인수 분해를 하려 했었네요;; 도움주셔서 더 짧은 코드로 더 빠르게 정확히 소인수 분해를 할수 있게 되었습니다. 인제 시간 초과만 잡으면 해결 할 수 있을것 같습니다. 감사합니다! 12년 전 link 정회원 권한이 있어야 커멘트를 다실 수 있습니다. 정회원이 되시려면 온라인 저지에서 5문제 이상을 푸시고, 가입 후 7일 이상이 지나셔야 합니다. 현재 문제를 푸셨습니다.
gloryof11
다시 질문방을 찾게 되었습니다;;
소인수분해를 하면 약수의 갯수를 찾을 수 있을것 같아서 아래와 같이 프로그래밍을 했습니다.
동작상 이상이 없는것 처럼 보이는데 2가지 문제가 있습니다;;
1) 예제 입력의 3번째, 200 1000000 2000000 의 답이 19 가 아닌 12가 나옴
2) 시간초과 발생
혹시 제가 생각을 잘못하고 만든 코드 인지 답답하여, 문제 해결하신 분들과 고수님들 에게 조언을 부탁드립니다;;
[[비밀번호 486|problem:PASS486]]
12년 전