HDU 2050

这个显然是要用递推式的嘛。
提示一点:从相交点入手。



先从简单的直线分割平面说起。


假设已经算完完了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]);
        }
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值