这个显然是要用递推式的嘛。
提示一点:从相交点入手。
先从简单的直线分割平面说起。
假设已经算完完了i-1条的结果f(i-1),第i条直线想要出现最大的结果一定要和前i-1条直线都相交才行。
这样子就出现了i-1个交点,这等价于出现了i-1+1个线段或射线(也就是说线段和射线的说亮一共是i-1+1个)
注意:一个线段或者一个射线可以对应一个新的部分。(具体我就不说了,可以自己看图)
所以加了第i条直线之后就多了i个新部分
所以有f(i)=i+f(i-1)
初始条件自己看看就看出来了。
然后再看折线。
折线可以看做是两个直线。
还是已经算完了i-1条折线的结果f(i-1),此时图上会有2*(i-1)条“直线”(之所以叫伪直线是因为两条直线相交之后不延伸了,但这在算交点个数的时候不影响,结果是一样的)
下面开始加第i条折线(可以看做是两条直线),也就是再加两条直线,想要结果最大,一定要和原先有的线全部相交。
先加一条,出现2*(i-1)个交点,出现2*(i-1)+1个线段或射线。
再加一条,出现2*i-1个交点,出现2*i个线段或射线。
由于真正加的不是两条直线而是一条折线,所以新加的这两条直线相交之后不再延伸,也就是少了2条射线。
一个射线或线段对应一个新部分。
所以加了第i条折线之后,一共出现了2*(i-1)+1+2*i-2=4*i-3个新部分。
所以f(i)=4*i-1+f(i-1);
AC的代码也比较简单。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <set>
using namespace std;
const int maxn=10010;
const int inf=0x3f3f3f3f;
int main()
{
long long f[maxn];
memset(f,0,sizeof(f));
f[1]=2;
for(int i=2;i<maxn;i++)
f[i]=4*i-3+f[i-1];
int n;
scanf("%d",&n);
while(n--)
{
int t;
scanf("%d",&t);
printf("%lld\n",f[t]);
}
}