zoukankan      html  css  js  c++  java
  • hoj1294

    用dfs进行整数拆分,对于每种情况计算组合数。为了避免重复计算,必须使用有重集的组合,com(f[i] - 1 + num[i], num[i]),这是num[i]个有i个节点的子树的情况总数。这个公式是用于求所选物品可重复选择,且重复选出的同一物品完全相同的情况。

    View Code
    #include <iostream>
    #include
    <cstdio>
    #include
    <cstdlib>
    #include
    <cstring>
    #include
    <cmath>
    using namespace std;

    #define maxn 41

    long long f[maxn], num[maxn], ans;
    int n;

    long long com(long long n, long long r)
    {
    // return C(n, r)
    if (n - r < r)
    r
    = n - r; // C(n, r) = C(n, n-r)
    long long i, j, s = 1;
    for (i = 0, j = 1; i < r; ++i)
    {
    s
    *= (n - i);
    for (; j <= r && s % j == 0; ++j)
    s
    /= j;
    }
    return s;
    }
    long long gcd(long long a, long long b)
    {
    return b?gcd(b,a%b):a;
    }

    long long C(long long n, long long m)
    {
    if(m > n - m ) m = n - m;
    long long mul = 1 , div = 1;
    for(int i = 0; i < m;i++)
    {
    mul
    *= (n-i);
    div
    *= (i+1);
    long long g = gcd(mul,div);
    mul
    /=g , div /= g;
    }
    return mul / div;
    }


    void dfs(int s, int left)
    {
    if (left == 0)
    {
    ans
    = 1;
    for (int i = 0; i <= n; i++)
    if (num[i] != 0)
    ans
    *= com(f[i] - 1 + num[i], num[i]);
    f[n]
    += ans;
    }
    if (s > left)
    return;
    num[s]
    ++;
    dfs(s, left
    - s);
    num[s]
    --;
    dfs(s
    + 1, left);
    }

    int main()
    {
    //freopen("D:\\t.txt", "r", stdin);
    //freopen("D:\\y.txt", "w", stdout);
    memset(num, 0, sizeof(num));
    f[
    1] = 1;
    f[
    2] = 1;
    for (n = 3; n <= 40; n++)
    {
    dfs(
    1, n - 1);
    //printf("f[%d]=%I64d;", n, f[n]);
    }
    while (scanf("%d", &n) != EOF)
    printf(
    "%I64d\n", f[n]);
    return 0;
    }
  • 相关阅读:
    20191117-STD::讲解及求平均数例题
    计算机网络-ip分类
    游标cursor
    ajax
    django ORM
    urls
    templates
    views
    models
    setting
  • 原文地址:https://www.cnblogs.com/rainydays/p/1988842.html
Copyright © 2011-2022 走看看