zoukankan      html  css  js  c++  java
  • [Ignatius and the Princess III] 整数的无序拆分(DP + 生成函数)

    整数的有序拆分就是隔板法,无序拆分则有两种处理方法

    DP递推

    • 我们假设P(n,m)P(n,m)是正整数nn无序拆分为mm个正整数的方案数

    • 对于某一种拆分,不妨将拆分出来的mm个数从小到大排序,分类讨论

      • 最小的数等于11,那么去掉这个11,相当于把剩下的n1n-1拆分成m1m-1个数,方案数就为P(n1,m1)P(n-1,m-1)
      • 最下的数大于11,那么将所有的数减去11,相当于把剩下的nmn-m拆分成mm个数,方案数就为P(nm,m)P(n-m,m)
    • 则最终答案为i=1nP(n,i)largesum_{i=1}^nP(n,i),时间复杂度为Θ(n2)large Theta(n^2)

    • AC code
      #include <bits/stdc++.h>
      using namespace std;
      int P[121][121];
      int main ()
      {
         for(int i = 1; i <= 120; ++i)
         {
         	P[i][1] = P[i][i] = 1;
         	for(int j = 2; j < i; ++j)
         		P[i][j] = P[i-1][j-1] + P[i-j][j];
         }
         for(int i = 1; i <= 120; ++i)
         	for(int j = 1; j <= i; ++j) //做前缀和
         		P[i][j] += P[i][j-1];
         int n;
         while(~scanf("%d", &n)) printf("%d
      ", P[n][n]);
      }
      

    生成函数/卷积

    • 想一想,显然可得答案为
      (1+x1+x2+...)(1+x2+x4+...)(1+x3+x6+...)...large (1+x^1+x^2+...)\*(1+x^2+x^4+...)\*(1+x^3+x^6+...)\*...所得多项式中次数为nn的系数
    • 因为是多项式的乘积,就是在每个多项式中选11项,最后再加起来。在第ii个多项式中,11表示数ii不选,xkix^{ki}表示选了kkii
    • 这实际上就是把加法运算,转化为多项式的次数来做乘法/卷积。思想类似于(分治)FFT等
    • 时间复杂度为Θ(n3)large Theta(n^3)
    • AC code
      #include <cstdio>
      #include <cstring>
      #include <cmath>
      #include <algorithm>
      using namespace std;
      const int MAXN = 121;
      int n, ans[MAXN], tmp[MAXN];
      int main ()
      {
      	while(~scanf("%d", &n))
      	{
      		for(int i = 0; i <= n; ++i)
      			ans[i] = 1, tmp[i] = 0;
      		for(int i = 2; i <= n; ++i)
      		{
      			for(int j = 0; j <= n; j+=i)
      				for(int k = 0; k + j <= n; ++k)
      					tmp[j+k] += ans[k];
      			for(int j = 0; j <= n; ++j)
      				ans[j] = tmp[j], tmp[j] = 0;
      		}
      		printf("%d
      ", ans[n]);
      	}
      }
      
  • 相关阅读:
    OSI安全体系结构
    PHP 二维数组根据相同的值进行合并
    Java实现 LeetCode 17 电话号码的字母组合
    Java实现 LeetCode 16 最接近的三数之和
    Java实现 LeetCode 16 最接近的三数之和
    Java实现 LeetCode 16 最接近的三数之和
    Java实现 LeetCode 15 三数之和
    Java实现 LeetCode 15 三数之和
    Java实现 LeetCode 15 三数之和
    Java实现 LeetCode 14 最长公共前缀
  • 原文地址:https://www.cnblogs.com/Orz-IE/p/12039444.html
Copyright © 2011-2022 走看看