C语言初学者的疑惑,不会,要求用递归

对于任意一个正整数n,总是可以找出正整数看k1、k2…,使得这些数想加刚好等于n,而且每个数都不超过指定数m。
问:对于给定的n,请找出共有多少中这样的求和式
注意;
设a,b不相等,则认为a+b与b+a是不同的求和式;
n=n也是一种求和式
例如:
n=4,m=2。
4=1+1+1+1
4=1+1+2
4=1+2+1
4=2+1+1
4=2+2


#include <stdio.h>

int cnt=0;

void comb(int a[],int m,int k,int s) 
{
    int i,j,t;
    for(i=m;i>=k;i--)
    {
        a[k]=i;

        if(k>1)
            comb(a,i-1,k-1,s);
        else
        {
            for(t=0,j=a[0];j>0;j--)
                t=t+a[j];
            
            if(t==s)
            {
                cnt++;
                printf("%d=", s);
                for(j=a[0];j>1;j--)
                printf("%d+", a[j]);
                printf("%d\n", a[1]);
            }
        }
    }
}

int main()
{
    int a[100],s,m,i;
    while (1)
    {
        scanf("%d %d", &s, &m);
        if (s == 0)
        {
            break;
        }
        
        cnt=0;
        for (i=1;i<=m;i++)
        {
            a[0]=i;
            comb(a,m,i,s);
        }
            printf("%d\n", cnt);
    }
    return 0;
}

运行结果:

img

“给定一个小点的输入,完整单步跟踪(同时按Alt+7键查看Call Stack里面从上到下列出的对应从里层到外层的函数调用历史)一遍。”是理解递归函数工作原理的不二法门!
递归函数关注以下几个因素
·退出条件
·参数有哪些
·返回值是什么
·局部变量有哪些
·全局变量有哪些
·何时输出
·会不会导致堆栈溢出

仅供参考:

#include <stdio.h>
#include <stdlib.h>
void print(int res[], int num) {
    static int L=0;
    L++;
    printf("%8d:",L);
    for (int i=0;i<num;++i) {
        printf(" %d", res[i]);
    }
    printf("\n");
}
void split(int n, int m) {// n表示总数,m表示最大因子
    static int res[100];// 保存结果
    static int num=-1;// 当前因子下标

    if (n<m || n<0 || m<1) return;
    num++;
    if (0==n) {// 递归终止条件,为0不可再分,直接输出
        print(res,num+1);
        num--;
        return;
    } else {
        if (n==m) {// 不拆,直接输出
            res[num]=m;
            print(res,num+1);
            num--;
        } else {
            // 拆分出第一个
            res[num]=m;
            n=n-m;

            if (m>n) m = n; // 最大因子不可能大于总数

            for (int i=m;i>=1;--i) {// 循环,第二个因子可以继续拆分,而且按照最大因子不同可以拆分成多个
                split(n,i);
            }
            num--;
        }
    }
}
void Split(int n) {
    if (n<=0) return;
    if (100<n) {
        printf("Up to 100\n");
        return;
    }
    for (int i=n;i>=1;--i) {
        split(n, i);
    }
}
void main(int argc,char **argv) {
         if (argc<=1) Split(5);
    else if (argc>=3) split(atoi(argv[1]),atoi(argv[2]));
    else              Split(atoi(argv[1]));
}