对于题库中 C.数字 中算重的情况的解释

我们如果要算一个长度(2n)的数列,使它前(n)位的和与后(n)位的和相等,奇数位与偶数位相等。

选数:

  • 我们先选出(2)个长度为(n/2)((n+1)/2)的序列编号为(A)(B)去填充前(n)个数。

  • 然后选出另外(2)个序列(A‘)(B’)(A')(A)长度相等,总和相等,(B')(B)长度相等,总和相等,也就是说这一共是四个不一定完全相同的序列),去填充后(n)个数。

构成:

  • 那么我们可以将最终的长为(2n)的序列前(n)个数由(A)(B)组成,后(n)个数用(A‘)(B’)组成。这样保证了前后相等(都等于(A+B))。

  • 对于奇偶位上的和相等,我们把(A)放在最终长为(2n)的序列前(n)个数中,并充当奇数位,将(B)放在前(n)个数中并充当偶数位。对于后(n)个数颠倒一下,将(A‘)充当后(n)个数的偶数位,(B’)充当奇数位,这样即可保证整个(2n)的序列奇偶位上的和相等(都等于(A+B))。

方案数:

  • 根据上面的推理,所以我们就要计算的方案数就是在一个(n)的序列中选四个长度分别为(n/2)((n+1)/2)(n/2)((n+1)/2)的总和相等的序列的方案数。

  • 再总结一下,我们需要控制的是(A和A')总和相等,长度都是((n+1)/2);(B和B')总和相等,长度都是(n/2)。也就是说(A)(B)(或者(A'和B')或者(A和B')或者(A'和B))没有必然联系,可以任意组合,但是相同的字母的序列有一定联系。

对于代码:

int lj=(n+1)/2,lo=n/2;
	for(int i=0;i<=lj*Max;++i)(ans1+=f[lj][i]*f[lj][i])%=M;//ans1即选出A和A‘的方案数
	for(int i=0;i<=lo*Max;++i)(ans2+=f[lo][i]*f[lo][i])%=M;//ans2即选出B和B’的方案数
	ans=(ans-(ans1*ans2%M)+M)%M;//ans1*ans2就是说在已经确定的许多A A‘ 和B B'中,任意两组都可以组合的,ans1*ans2就是A A' B B'所有的方案(也就是算重的)
原文地址:https://www.cnblogs.com/Lour688/p/13324580.html