牛客网小白赛:圆(组合数+欧拉示性数公式+图+帕斯卡三角形)

传送门

首先了解欧拉示性数公式:

平面上有V个点,E条互不相交的直线,划分出F个区域,符合V-E+F=2这个公式1,可以画图推导

接着还得了解一个公式:N条直线相交于M个点,最后划分出了多少个线段,公式2:N+2*M

接着继续看这个问题:求一个圆上取N个点,最多把圆划分成几个区域

首先想下N个点两两之间构成直线,最后可以构成多少条直线呢?

不就是C(N,2)么

还得想下在圆内一共有多少个交点,从直线考虑太复杂了,我们可以发现圆上每4个点构成一个内部的交点,所以数量不就是C(N,4)么

最后总的点数V就是C(N,4)+N(套用了公式2)

总的边数就是C(N,2)+2*C(N,4)+N

最后套用公式1:F=E-V+1(因为只算圆内,所以外围那个大区域减掉),C(N,2)+2*C(N,4)+N-(C(N,4)+N)+1=C(N,2)+C(N,4)+1

附上AC代码:

此处又使用了一个组合数打表,可以优化下时间

传送门

#include<iostream>
#include<cstdio>

using namespace std;

typedef long long ll;

const int maxn=1e4+10;

ll s[maxn][5];

void mt()
{
    for(int i=0;i<maxn;i++){
        s[i][0]=1;
    }
    for(int i=1;i<maxn;i++){
        for(int j=1;j<5;j++){
            s[i][j]=s[i-1][j-1]+s[i-1][j];
        }
    }
}

int main()
{
    mt();
    ll n;
    while(~scanf("%lld",&n)){
        printf("%lld\n",s[n][2]+s[n][4]+1);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/zhouzi2018/article/details/81162292