900字范文,内容丰富有趣,生活中的好帮手!
900字范文 > 关于m个n-1维几何体最大分割n维空间问题的解法

关于m个n-1维几何体最大分割n维空间问题的解法

时间:2019-09-05 10:58:19

相关推荐

关于m个n-1维几何体最大分割n维空间问题的解法

关于m个n-1维几何体最大分割n维空间问题的解法

1.前置知识2.空间关系与基本递推式3.递推式的优化4.程序的进一步优化5.AC代码6.总结7.测试数据

定义 f(n,m)f(n,m)f(n,m) 表示n个m-1维几何体最大分割m维空间的个数,求给定的n,m的 f(n,m)f(n,m)f(n,m)对1e9+7取模。(n<=1e9,m<=1e7)

时间限制:1s 空间限制: 512mb

例如,f(1,2)=2;f(2,3)=4;f(3,3)=8f(1,2)=2;f(2,3)=4;f(3,3)=8f(1,2)=2;f(2,3)=4;f(3,3)=8。(画下图就能理解了)

然后试着去想一下为什么f(4,3)=15f(4,3)=15f(4,3)=15(不是14,要细致考虑怎么画图)。

接下来开始细致讲解。

1.前置知识

一定的空间想象能力,逆元,组合数,杨辉三角。

2.空间关系与基本递推式

如果你能推出来f(4,3)=15f(4,3)=15f(4,3)=15并能归纳出递推式的话,你的理解力已经很强了,可以直接看第三部分了。

好,f(3,3)f(3,3)f(3,3)是在三个维度上各切一刀,这个是很显然的,那么f(4,3)f(4,3)f(4,3)一定是在这三刀的基础上切的,怎么切呢?

我们先来考虑直线分割平面,在两个维度个切一刀后,我们考虑f(3,2)f(3,2)f(3,2)的情况。

显然,为了分割最大,我们让第三条直线与已经切好的两条直线都相交。这样子我们顺利得到了f(3,2)=7f(3,2)=7f(3,2)=7。

实际上,我们继续考虑:

f(3,2)=7;f(2,1)=3;f(2,2)=4;f(3,2)=7;f(2,1)=3;f(2,2)=4;f(3,2)=7;f(2,1)=3;f(2,2)=4;

你是否发现了什么?

继续考虑f(4,2)

将三条直线都经过一次,我们显然得到了f(4,2)=11f(4,2)=11f(4,2)=11。

继续往下考虑:

f(4,2)=11;f(3,1)=4;f(3,2)=7;f(4,2)=11;f(3,1)=4;f(3,2)=7;f(4,2)=11;f(3,1)=4;f(3,2)=7;

那么回到f(4,3)f(4,3)f(4,3)上。

我们类比二维的,让第四个平面与已经切好的三个平面相交。

f(4,3)=15;f(3,2)=7;f(3,3)=8;f(4,3)=15;f(3,2)=7;f(3,3)=8;f(4,3)=15;f(3,2)=7;f(3,3)=8;

因为高维空间无法直观观察,所以我们递推:

现在是m维的已经切好了n-1刀,有:

1 .如果还有维度没有分割,分割这个维度。

2 .维度都分割完了,那么把所有已分割的“刀”都经过一次。

归纳一下,实际上就是新的一“刀”要把之前的“刀”全经过一次。

至此,我们已经得到基本递推式:

f(n,m)=f(n−1,m−1)+f(n−1,m)f(n,m)=f(n-1,m-1)+f(n-1,m)f(n,m)=f(n−1,m−1)+f(n−1,m)

3.递推式的优化

上述方法的复杂度是O(nm)O(nm)O(nm)的,只能通过60pts。

我们思考怎么优化。

从特例入手,我们考虑展开f(4,4)f(4,4)f(4,4)。

f(4,4)=f(3,3)+f(3,4)f(4,4)=f(3,3)+f(3,4)f(4,4)=f(3,3)+f(3,4)

f ( 3 , 2 )=f(2,2)+2f(2,3)+f(2,4)=f(2,2)+2f(2,3)+f(2,4)=f(2,2)+2f(2,3)+f(2,4)

f ( 3 , 2 )=f(1,1)+3f(1,2)+3f(1,3)+f(1,4)=f(1,1)+3f(1,2)+3f(1,3)+f(1,4)=f(1,1)+3f(1,2)+3f(1,3)+f(1,4)

f ( 3 , 2 )=f(0,0)+4f(0,1)+6f(0,2)+4f(0,3)+f(1,4)=f(0,0)+4f(0,1)+6f(0,2)+4f(0,3)+f(1,4)=f(0,0)+4f(0,1)+6f(0,2)+4f(0,3)+f(1,4)

很显然,只要是维度大于0的空间,什么都不做只有自己这一份,所以f(0,m>=0)=1f(0,m>=0)=1f(0,m>=0)=1

然后我们观察展开过程中,系数都是杨辉三角上的数。

根据组合数学知识,我们很容易知道,杨辉三角上的数对应是这一层的组合数。

第x层上都是Cx0−>x+1C^{0->x+1}_xCx0−>x+1​(定义顶层为第0层)。

那么很显然,当n>=m时,杨辉三角不会出现溢出的情况(溢出是与n < m相对的),答案就是分解到n=0时候这一层杨辉三角的和,对应化简式:

∑i=0nCni\sum_{i=0}^nC^i_n∑i=0n​Cni​

由组合知识可以得到和为2n2^n2n

那么当n < m的时候,我们很容易发现这个时候杨辉三角溢出了(即存在n降到0时展开式有m为负数的情况,可以自己展开一个式子理解一下溢出)。

很显然,从几何意义来看,那些溢出的部分是0,怎么可能存在负维的几何空间(至少这道题不涉及,可能未来会存在?)。

那么会发现,我们从n-m到-1这些部分都是0(这里指组合数C的第二个参数),只需要考虑n这层杨辉三角从0到m的项。

那么显然,答案就是:

∑i=0mCni\sum_{i=0}^mC^i_n∑i=0m​Cni​

归纳之后,发现第一种情况实际上可以并入第二种情况之中。

所以,最终结果就出来了。

f(n,m)=∑i=0mCnif(n,m)=\sum_{i=0}^mC^i_nf(n,m)=∑i=0m​Cni​

到现在,这道题可以拿90pts了。(毕竟还有n<=1e9的毒瘤数据)

4.程序的进一步优化

上述的式子用阶乘逆元求组合数时间复杂度看似是O(max(n,m))O(max(n,m))O(max(n,m)),实际上常数非常大,加之n可能是1e9所以这种算法显然是AC不掉的。

所以必须先预处理逆元,然后递推组合数,这部分知识忘记要复习啊,这是很简单的,实在不会可以看代码。

然后还有一个细节处理,我们知道组合数也可以递推,所以我们多推一层,这样,我们的总时间复杂度是O(m+m/2)O(m+m/2)O(m+m/2)。(不要忘了m也很大,常数大点不优化是过不去的。)

至此,本题AC。

5.AC代码

AC链接

#include<bits/stdc++.h>//author:Displaceusing namespace std;typedef long long ll;const ll mod=1e9+7;int n,m;ll inv[10100000];ll c[10100000];int main(){scanf("%d%d",&n,&m);inv[0]=inv[1]=1;for(int i=2;i<=m;i++)inv[i]=(mod-mod/i)*inv[mod%i]%mod;//递推逆元c[0]=1;ll ans=0;for(int i=0;i<=m;i++)c[i+1]=c[i]*(n+1-i)%mod*inv[i+1]%mod;//递推组合数for(int i=m;i>=0;i-=2) ans=(ans+c[i])%mod;//求和printf("%lld\n",ans);return 0;}

6.总结

AC掉本题首先需要很强的空间想象能力,能够推出递推式。赛场上我想到了这个做法,拿到了60pts。

然后还需要大胆尝试,化简式很难得到,网上很多大佬们的化简过程很复杂,自认为我的化简应该很简单易懂了。

以及基本的数论知识,除了难想,这道题是很基础的求组合数模板题。

感谢PFCC化简部分思路启发和P_Pqueen的几何意义部分证明思路启发。

7.测试数据

test1:

input:4 2

output:11

test2:

input:5 3

output:26

test3:

input:75 755

output:64050

test4:

input:622 419

output:205583450

test5:

input:905 360

output:148409321

test6:

input:560 264

output:193032641

test7:

input:8943435 96993

output:460917255

test8:

input:3209277 922975

output:662850536

test9:

input:345510 344081

output:762374184

test10:

input:439178595 5730641

output:881542483

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。