zoukankan      html  css  js  c++  java
  • BZOJ 1197 [HNOI2006]花仙子的魔法 (数学题)

    题面:洛谷传送门 BZOJ传送门

    非常有意思的一道数学题,浓浓的$CF$风,然而我并没有想出来..

    我们想把一个$n$维空间用$n$维球分成尽可能多的块

    而新增加一个$n$维球时,肯定要尽可能多地切割前几个球围成的不同空间

    画画图容易发现$n=1$的规律,因为一条线段只能在两个端点处切割这条直线,所以$f(n)=2n$

    $n=2$的规律不太好找,但突破口也在这了..

    发现当一个新的圆加入到图里时,新圆会切割原来的圆,把原图分成了更多的小块

    我们把新圆的圆周看成一条线段,把旧圆和新圆的两个交点形成的弧看成一条线段

    诶?问题似乎变成了一维的,事实上我们是再用一个新的直线去切原来的直线

    原来直线数目是$(i-1)$,因此$f[i]=f[i-1]+2(i-1)$

    那如果把这个问题推广到更高的维度呢?

    结论还是成立的,我们在i维空间内,用一个$i$维球去切$j-1$个$i$维球

    新产生的块数目就是用$i-1$维球去切$j-1$个$i-1$维球

    因此得到递推式$f[i,j]=f[i-1,j-1]+f[i,j-1]$

     1 #include <cmath>
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <algorithm>
     5 #define N1 105
     6 #define ll long long
     7 #define ull unsigned long long 
     8 #define dd double
     9 #define inf 0x3f3f3f3f
    10 using namespace std;
    11 
    12 int gint()
    13 {
    14     int ret=0,fh=1;char c=getchar();
    15     while(c<'0'||c>'9'){if(c=='-')fh=-1;c=getchar();}
    16     while(c>='0'&&c<='9'){ret=ret*10+c-'0';c=getchar();}
    17     return ret*fh;
    18 }
    19 
    20 ull f[N1][N1];
    21 int n,m;
    22 
    23 int main()
    24 {
    25     scanf("%d%d",&m,&n); int i,j;
    26     for(i=1;i<=n+1;i++)
    27         for(j=2,f[i][1]=2;j<=m;j++)
    28             f[i][j]=f[i-1][j-1]+f[i][j-1];
    29     printf("%llu
    ",f[n+1][m]);
    30     return 0;
    31 }
  • 相关阅读:
    C# 二维码 ThoughtWorks.QRCode.dll
    Asp.net生命周期
    进程和线程,多线程等使用方法
    反射的使用与定义
    《委托和事件》
    《泛型集合》
    第三课时《枚举》
    数据库字段包括数组中的每一项
    .NetCore 图片压缩
    NetCore3.0 EF修改
  • 原文地址:https://www.cnblogs.com/guapisolo/p/10303950.html
Copyright © 2011-2022 走看看