猫王相亲

题目大意

给定一个金字塔,从第二层起每一层中的数均等于下面一层左右的两个数之和。给定正整数$n(n\le10^5)$,金字塔的第一层为$1$到$n$从小到大排列而成的数列,求金字塔顶的数。

数列特征

从已知条件只能知道第一行为$1~N$的等差数列。

假设第一行中某三个连续的数字为$a-d, a, a+d$,($d$为等差数列的公差,此处$d=1$),那么第二行对应的数为$2a-d,2a+d$,相差$2d$,由于$a$的一般性,所以对于第二行任意两项的差都为$2d$,以此类推每一行的数列都组成等差数列,第$i$行数列的公差为$d_i=2^{i-1}$。

首项的值

推导出公差之后,只要知道数列的首项,就能很快得出整个数列,而最后求的是金字塔顶的数,就相当于最顶上一层的首项,所以设$F_i$为第$i$层的首项。

根据每个数等于下一层左右两个数的和,那么就有
$$\begin{array}\\F_i&=&F_{i-1}+(F_{i-1}+d_{i-1}) \\&=&2F_{i-1}+2^{i-1} \end{array}$$

代入$n$,则有

$$\begin{array} \\ F_n&=&2F_{n-1}+2^{n-2} \\ &=&2(2F_{n-2}+2^{n-3})+2^{n-2}&=&4F_{n-2}+2\cdot 2^{n-2} \\ &=&4(2F_{n-3}+2^{n-4})+2^{n-2}&=&8F_{n-3}+3\cdot 2^{n-2} \\&=&……\\ _{第i行}&=&2^iF_{n-i}+i\cdot 2^{n-2} \\ _{当i=n-1时}&=&2^{n-1}F_1+(n-1)\cdot 2^{n-2} \\ &=&(n+1)\cdot 2^{n-2} \end{array}$$

所以只要高精度加个快速幂就好了。

代码

  1 #include <cstdio>
  2 #include <cstring>
  3 
  4 struct BigNumber
  5 {
  6     static const long long BASE = 1000000000;
  7     static const int BASEDIGS = 9;
  8     
  9     int ndigs;
 10     long long *digs;
 11     
 12     void init(int n, const long long *d)
 13     {
 14         while (n > 0 && d[n - 1] == 0)
 15             --n;
 16         ndigs = n;
 17         digs = new long long[n];
 18         for (int i = 0; i < n; ++i)
 19             digs[i] = d[i];
 20     }
 21     
 22     BigNumber(int n, const long long *d)
 23     {
 24         init(n, d);
 25     }
 26     
 27     BigNumber(long long x = 0)
 28     {
 29         long long d[2];
 30         d[0] = x % BASE;
 31         d[1] = x / BASE;
 32         init(2, d);
 33     }
 34     
 35     BigNumber operator *(const BigNumber &a) const
 36     {
 37         int n = ndigs + a.ndigs;
 38         long long d[n], p;
 39         for (int i = 0; i < n; i++)
 40             d[i] = 0;
 41         for (int i = 0; i < ndigs; i++)
 42         {
 43             p = 0;
 44             for (int j = 0; j < a.ndigs; j++)
 45             {
 46                 long long v = digs[i] * a.digs[j];
 47                 long long v1 = v / BASE, v0 = v % BASE;
 48                 d[i + j] += v0 + p;
 49                 p = v1 + d[i + j] / BASE;
 50                 d[i + j] %= BASE;
 51             }
 52             for(int j = i + a.ndigs; p > 0; ++j)
 53             {
 54                 d[j] += p;
 55                 p = d[j] / BASE;
 56                 d[j] %= BASE;
 57             }
 58         }
 59         return BigNumber(n, d);
 60     }
 61 
 62     BigNumber operator *(long long x) const
 63     {
 64         int n = ndigs + 1;
 65         long long d[n];
 66         long long a = 0;
 67         for (int i = 0; i < ndigs; i++)
 68         {
 69             a += digs[i] * x;
 70             d[i] = a % BASE;
 71             a /= BASE;
 72         }
 73         d[ndigs] = a;
 74         return BigNumber(n, d);
 75     }
 76 
 77     void write() const
 78     {
 79         if (ndigs == 0) printf("0");
 80         else
 81         {
 82             printf("%lld", digs[ndigs - 1]);
 83             for (int i = ndigs - 2; i >= 0; i--)
 84                 printf("%0*lld", BASEDIGS, digs[i]);
 85         }
 86     }
 87 };
 88 
 89 int n;
 90 
 91 BigNumber pow(BigNumber x, int p)
 92 {
 93     if (p == 0) return BigNumber(1);
 94     if (p == 1) return x;
 95     if (p == 2) return x * x;
 96     if (p & 1) return pow(pow(x, p / 2), 2) * x;
 97     return pow(pow(x, p / 2), 2);
 98 }
 99 
100 int main()
101 {
102     scanf("%d", &n);
103     if (n == 1) printf("1");
104     else (pow(BigNumber(2), n - 2) * (n + 1)).write();
105 }

 

posted @ 2015-06-30 12:19  Lightning34  阅读(325)  评论(0编辑  收藏  举报