trees 
一个简单的数学题,只需要将树按高度排序,计算以 i i i   为最大值时选取的方案数即可。
#include  <bits/stdc++.h>  using  namespace  std;struct  Rhine_Lab  {    Rhine_Lab ()     {         freopen ("trees.in" , "r" , stdin);         freopen ("trees.out" , "w" , stdout);     } }; Rhine_Lab Ptilopsis_w; typedef  long  long  ll;const  int  N = 100005 ;const  int  P = 1e9 +7 ;int  n, k;ll val[N]; ll fact[N], finv[N]; void  prework (int  n)  ;ll qpow (ll a, ll b)  ;ll C (ll n, ll m)  ;int  main ()  {    scanf ("%d%d" , &n, &k);     for (int  i = 1 ; i <= n; i++)         scanf ("%lld" , &val[i]);     stable_sort (val+1 , val+n+1 );          prework (n);          ll ans = 0 ;     for (int  i = k; i <= n; i++)     {         ans += val[i]*C (i-1 , k-1 )%P;         ans %= P;     }     printf ("%lld" , ans); } ll C (ll n, ll m)   {    if (n < m) return  0 ;     return  fact[n] * finv[m]%P * finv[n-m]%P; } void  prework (int  n)  {    fact[0 ] = 1 ;     for (int  i = 1 ; i <= n; i++)         fact[i] = fact[i-1 ]*i%P;          finv[n] = qpow (fact[n], P-2 );     for (int  i = n-1 ; i >= 0 ; i--)         finv[i] = finv[i+1 ]*(i+1 )%P; } ll qpow (ll a, ll b)   {    ll ans = 1 ;     for (; b; b >>= 1 , a = a*a%P)         if (b&1 ) ans = ans*a%P;     return  ans; } 
 
bridge 
这题题意有一些不清楚,题目问的是: 从一个特定点开始,可以左右走,最后回到这个点,且每两次经过这个点的时间间隔不超过 m m m   。
我们可以用DP搞,设 f i f_{i} f i    表示走 i i i   步回到起点且满足时间限制的方案数。
因为向左走和向右走是对称的,所以只计算其中一种然后乘 2 2 2   即可。
这时我们需要求出走 2 x 2x 2 x   步回到起点的方案数,且中途不能回到起点。(防止重复)
这个中途不能回到起点比较难计算,我们可以先走一步离开起点,然后计算可以回到起点的方案数,再走一步回来的方案数,将其设为 d 2 x d_{2x} d 2 x  
所以转移方程就很好写了: f i = ∑ j = 2 m f i − j ∗ d j − 2 ∗ 2 f_i = \sum_{j=2}^{m} f_{i-j}*d_{j-2}*2 f i  = ∑ j = 2 m  f i − j  ∗ d j − 2  ∗ 2 
因为这是个常系数转移方程,可以矩阵加速递推优化。
#include  <bits/stdc++.h>  using  namespace  std;struct  Rhine_Lab  {    Rhine_Lab ()     {         freopen ("bridge.in" , "r" , stdin);         freopen ("bridge.out" , "w" , stdout);     } }; Rhine_Lab Ptilopsis_w; typedef  long  long  ll;const  int  P = 1e9 +7 ;namespace  Matrix {    int  lim;     struct  matrix  {         ll a[105 ][105 ];         matrix () { memset (a, 0 , sizeof  (a)); }         ll* operator  [] (int  x) { return  a[x]; }     };     matrix operator  * (matrix a, matrix b)     {         matrix c;         for (int  i = 1 ; i <= lim; i++)         for (int  j = 1 ; j <= lim; j++)         for (int  k = 1 ; k <= lim; k++)             (c[i][j] += a[i][k]*b[k][j]%P) %= P;         return  c;     } } using  namespace  Matrix;int  n, m;ll d[105 ][105 ]; matrix f, g; int  main ()  {    scanf ("%d%d" , &n, &m);     d[0 ][0 ] = 1 ;     for (int  i = 1 ; i <= m; i++)     for (int  j = 0 ; j <= i; j++)     {         if (j != i) (d[i][j] += d[i-1 ][j+1 ]) %= P;         if (j != 0 ) (d[i][j] += d[i-1 ][j-1 ]) %= P;     }     Matrix::lim = m;     for (int  i = 1 ; i < m; i++)         g[i+1 ][i] = 1 ;     for (int  i = m-1 ; i >= 1 ; i--)         g[i][m] = 2 *d[m-i-1 ][0 ]%P;          f[1 ][m] = 1 ;     for (; n; n >>= 1 , g = g*g)         if (n&1 ) f = f*g;     printf ("%lld" , f[1 ][m]);      } 
 
flowers 
一道规律题,每一位上都有循环节,且第 i i i   位的循环节为 2 i 2^i 2 i   (不一定是最小循环节)。
这时我们可以枚举每一位,循环的部分直接算就行,剩下的部分就暴力统计即可。
#include  <algorithm>  #include  <cstdio>  using  namespace  std;struct  Rhine_Lab  {    Rhine_Lab ()     {         freopen ("flowers.in" , "r" , stdin);         freopen ("flowers.out" , "w" , stdout);     } }; Rhine_Lab Ptilopsis_w; typedef  long  long  ll;ll val, b, n; ll calc (ll cnt, ll bit)  ;ll solve (ll a, ll b, ll n)  ;int  main ()  {    int  t; scanf ("%d" , &t);     while (t --> 0 )     {         scanf ("%lld%lld%lld" , &val, &b, &n);         printf ("%lld\n" , solve (val, b, n));     } } ll solve (ll a, ll b, ll n)   {    ll ans = 0 ;     ll lowbit = (a&-a);     ll maxn = b+a*n;     for (ll i = 1 ; i < lowbit; i <<= 1 )         ans += n*((b&i)!=0 );     for (ll i = lowbit; i <= maxn; i <<= 1 )         ans += i*(n/(i<<1 ));     for (ll i = lowbit; i <= maxn; i <<= 1 )         ans += calc (n%(i<<1 ), i<<1 );     return  ans; } ll calc (ll x, ll bit)   {    ll ans = 0 ;     for (ll i = 1 ; i <= x; i++)     {         ll val = (b+val*i)%bit;         if (val < (bit>>1 ))             i = min (x, i + ((bit>>1 )-1 -val)/val);         else          {             ll r = min (x, i + (bit-1 -val)/val);             ans += r-i+1 ;             i = r;         }     }     return  ans; }