Bài toán tìm giai thừa

Hôm nay phỏng vấn được hỏi một câu. “Bạn hãy viết 1 chương trình C, có 1 hàm, đệ qui, để tìm giai thừa của một số”
Thế là cặm cuội viết lên bảng, kết quả chị ấy bảo “Tôi yêu cầu có 1 hàm thôi mà”. Vì do viết tận 2 hàm main() và get_ factorial() nên bị đánh giá: “ẩu tả :))”.
Giờ ngồi tìm cách giải và thấy nó cũng thú vị nên muốn chia sẽ một chút, không biết các bạn có đáp án như thế nào. :smiley:

1 Like
#include <iostream>
using namespace std;

int main() {
    int n, factorial = 0;
    cin >> n;
    factorial = n;
    for (int i = 1; i < n; i++) {
        factorial = factorial*(n-i);
    }
    cout << factorial << endl;
    return 0;
}

đây là code của em, còn đệ quy thì… chưa có khái niệm gì về nó :v

6 Likes

Kệ bà chị đó đi, làm như bả mới ẩu, ai chơi đệ quy main() bao giờ.

6 Likes

Thật sự câu hỏi của bà này mang tính đánh đố nhiều hơn là hỏi kĩ năng của ứng viên. Key ở câu hỏi này là viết được hàm tính giai thừa chứ không phải chỉ dùng 1 hàm bằng mọi giá

4 Likes

Hi lahata.
Theo mình thì hàm main hoàn toán có thể gọi đệ quy như bình thường vấn đề là làm thế nào biết nó là hàm gọi đầu tiên. Cách đơn giản dựa vào 2 biến int argc, char **argv tham số đầu vào của chương trình (mình thường dùng cho tham số lệnh trên Linux). argc luôn lớn hơn 1 vì nó chỉ số phần tử của mảng argv mà mảng argv luôn có ít nhất 1 phần tử là tên chương trình. Từ đó có thể áp dụng:

CLICK ME
#include <iostream>                                                             
                                                                                
using namespace std;                                                            
                                                                                
int main(int argc, char **argv = nullptr) {                                     
    if(argv != nullptr) {                                                       
        cout << "Input" << endl;                                                
        cin >> argc;                                                            
        cout << main(argc) << endl;
        return 0;
    }
    return argc == 0 ? 1 : argc * main(argc - 1);
}

P/S Cái này nó chỉ như một mẹo nhỏ. Tuy nhiên giải bài toán bằng mẹo thì không nên khuyến khích mà chỉ coi đó như một kiên thức mở rộng về hàm.

Haha phải chép bài ngay.

7 Likes

Hi all, mục đích câu hỏi chắc là kiểm tra cách dùng hàm main, đây là cách giải của mình

#include<stdio.h>
#define N 10

int main(int num)
{
    static int cnt;
    static int ret = 1;

    cnt = num;

	if (cnt <= N) {
        ret = ret * num;
        main(cnt + 1);
	} else {
	    printf("%d!=%d \n", N, ret);
	    return 0;
	}
}

Dù gì mình nghĩ bài này cũng khá hay, biết đâu một ngày nào đó có người hỏi lại :smiley: :smiley:

1 Like

cho argc là num thì làm sao chạy chương trình :V

sao ko hỏi bả đáp án rồi chửi bả lại :V :V :V

4 Likes

Kaka, chỉ cấn lấy hàm main(int argc) chạy với đối số, hoặc để cho argc bằng 1 là được :sunny:

biên dịch ra ví dụ a.exe rồi chạy chương trình làm sao? Ví dụ muốn tính 10 giai thừa thì run chương trình thế nào?? a.exe 10 à? Ko có input output gì hết sao biết tìm giai thừa của số mấy???

email hỏi bả đi em, trước là cám ơn vì đã dành thời gian phỏng vấn em, sau là hỏi bả đáp án bài này, chứng tỏ em ham học hỏi, và rất ấn tượng với buổi trình phỏng vấn đó. Có đáp án xong post lên đây để chúng ta cùng chửi à ko cùng học hỏi :flushed:

5 Likes

Hi lahata.
Ý tưởng dùng biến tĩnh làm cờ trạng thái cũng rất hay.

#include <stdio.h>                                                              
                                                                                
int main() {                                                                    
    static int flag = 1;                                                        
    static int ret = 0;                                                         
    if(flag) {                                                                  
        printf("Input\n");                                                      
        scanf("%d", &ret);                                                      
        flag = 0;                                                               
        printf("%d\n", main());                                                 
        return 0;                                                               
    }                                                                           
    return ret == 0 ? 1 : ret-- * main();                                       
}

P/S Cái này khá giống với fork. Tuy nhiên dùng biến static làm cho hàm nhìn không đẹp lắm.

Haha phải chép bài ngay.

6 Likes

Mình chạy a.exe 1 2 3 4 5 6 7 8 9 lúc đó argc là 10, code dưới này mình vừa test thử theo cách chạy của bạn.

HR gửi mail PV, muốn biết email người PV thì phải xin. Thôi cũng không cần thiết.

1 Like

rảnh dữ ngồi viết 10 argument khi chạy à :V Thế double click vô a.exe có chạy đc ko :V

mà thôi miễn sao xài được là được, câu hỏi kỳ cục thì đáp án cũng kỳ cục cho dzui :V

4 Likes

Hoặc có thể giải như bạn ở trên.

#include <stdio.h>

int main(int n, char** argv)
{
    if (argv)
        puts("Enter n"), scanf("%d", &n), printf("%d! = %d\n", n, main(n, 0));
    else 
        return n ? n * main(n - 1, 0) : 1;
}

ngắn nè :V rút gọn từ cách của @Phong_Ky_Vo xài argc argv :V
ngắn quá ko có ktra số âm, nhập vào số âm thì thăng :V

làm phát này có lẽ đi về luôn khỏi phỏng vấn nữa :smiling_face_with_three_hearts:

#include <stdio.h>

int main(int n, char** argv)
{
    return argv ? puts("Enter n"), scanf("%d", &n),
           printf("%d! = %d\n", n, main(n, 0)), 0 : n ? n * main(n - 1, 0) : 1;
}
6 Likes

nhảm nhí, viết thuật toán ai đi viết hàm main, có viết cũng không tính, cty xl vote đi nơi khác

2 Likes
83% thành viên diễn đàn không hỏi bài tập, còn bạn thì sao?