64,660
社区成员
发帖
与我相关
我的任务
分享
static public long getSetsNum1(int n)
{
/计算 总合, 如果为奇数, 返回 0
long sum = 0;
for (int i = 1; i <= n; ++i) sum += i;
if ((sum & 1) == 1) return 0;
sum >>= 1;
//初始化数组 统计用
//数组 dp[i] 表示 总和为i的集合总数
//数组长度 到 sum/2 + i 就好了, 我这边懒得计算, 就用 sum了
long N = ((n * (n + 1)) >> 1) + 2;
long[] dp = new long[N];
for (long i = 1; i < N; ++i) dp[i] = 0;
//递推 BigO(N^3)
dp[0] = 1;
long max = 0;
// 每次循环计算 1 ~ i 可以组成的集合的数目, 并入统计数组
// 假设 i - 1 得到的数组 为 x1,x2, ..... xn
// 第i 次计算, 只需要 基于 i - 1 的数组, 加上 i的情况, 就可以得到i 的统计数组
for (long i = 1; i <= n; ++i)
{
// 这里剪去了集合的和超过的情况
for (long j = max < sum ? max : sum; j >= 0; --j) dp[j + i] += dp[j];
max += i;
}
//dp[i] 就存放的是总合为i 的集合总数
return dp[sum] >> 1;
}
//算法复杂度BigO(2^N), 比 那种 N!的递归 剪枝 逻辑上清楚很多
//从前往后递归,对于每个数字, 都有加和不加两种情况
static public long getSetsNum2(long sum, int i, int n)
{
//当前的数字总合 〉 sum 或者 已经走到 队尾,则该集合不符合要求,返回 0
if (i > n ||sum < 0) return 0;
// 数字总和 == sum, 集合符合要求, 返回1
if (sum == 0) return 1;
//递归 下一个数字
return getSetsNum2(sum, i + 1, n) + getSetsNum2(sum - i, i + 1, n);
}
static public long getSetsNum2(int n)
{
//计算 总合, 如果为奇数, 返回 0
long sum = 0;
for (int i = 1; i <= n; ++i) sum += i;
if ((sum & 1) == 1) return 0;
sum >>= 1;
//统计和的为 sum/2 的集合总数 , 返回 其 1/2
return getSetsNum2(sum, 0, n) >> 1;
}
class Program
{
static public long getSetsNum1(int n)
{
//check total sum
long sum = 0;
for (int i = 1; i <= n; ++i) sum += i;
if ((sum & 1) == 1) return 0;
sum >>= 1;
//inital array
long N = ((n * (n + 1)) >> 1) + 2;
long[] dp = new long[N];
for (long i = 1; i < N; ++i) dp[i] = 0;
//递推 BigO(N^3)
dp[0] = 1;
long max = 0;
for (long i = 1; i <= n; ++i)
{
for (long j = max < sum ? max : sum; j >= 0; --j) dp[j + i] += dp[j];
max += i;
}
return dp[sum] >> 1;
}
static public long getSetsNum2(long sum, int i, int n)
{
if (i > n||sum < 0) return 0;
if (sum == 0) return 1;
return getSetsNum2(sum, i + 1, n) + getSetsNum2(sum - i, i + 1, n);
}
static public long getSetsNum2(int n)
{
long sum = 0;
for (int i = 1; i <= n; ++i) sum += i;
if ((sum & 1) == 1) return 0;
sum >>= 1;
return getSetsNum2(sum, 0, n) >> 1;
}
static void Main(string[] args)
{
for (int i = 1; i < 22; ++i)
{
Console.WriteLine("n=" + i);
Console.WriteLine(getSetsNum1(i));
Console.WriteLine(getSetsNum2(i));
}
Console.ReadLine();
}
}
class Program
{
static public long getSetsNum1(int n)
{
//check total sum
long sum = 0;
for (int i = 1; i <= n; ++i) sum += i;
if ((sum & 1) == 1) return 0;
sum >>= 1;
//inital array
long N = ((n * (n + 1)) >> 1) + 2;
long[] dp = new long[N];
for (long i = 1; i < N; ++i) dp[i] = 0;
//递推 BigO(N^3)
dp[0] = 1;
long max = 0;
for (long i = 1; i <= n; ++i)
{
for (long j = max < sum ? max : sum; j >= 0; --j) dp[j + i] += dp[j];
max += i;
}
return dp[sum] >> 1;
}
static public long getSetsNum2(long sum, int i, int n)
{
if (i > n) return 0;
if (sum == 0) return 1;
return getSetsNum2(sum, i + 1, n) + getSetsNum2(sum - i, i + 1, n);
}
static public long getSetsNum2(int n)
{
long sum = 0;
for (int i = 1; i <= n; ++i) sum += i;
if ((sum & 1) == 1) return 0;
sum >>= 1;
return getSetsNum2(sum, 0, n) >> 1;
}
static void Main(string[] args)
{
for (int i = 1; i < 22; ++i)
{
Console.WriteLine("n=" + i);
Console.WriteLine(getSetsNum1(i));
Console.WriteLine(getSetsNum2(i));
}
Console.ReadLine();
}
}