【BZOJ 3028】食物

传送门


problem

有若干种物品,每种物品选取的限制如下:

  • A A A:偶数个
  • B B B 0 0 0 个或 1 1 1
  • C C C:小于等于 2 2 2
  • D D D:奇数个
  • E E E 4 4 4 的倍数个
  • F F F 0 0 0个, 1 1 1 个, 2 2 2 个或 3 3 3
  • G G G:不超过一个
  • H H H 3 3 3 的倍数个

求从中选择n个物品的方案数模 10007 10007 10007 的结果。

数据范围: n ≤ 1 0 500 n\le10^{500} n10500


solution

这道题重在思维,代码非常简单。

我们先把这 8 8 8 种东西的生成函数搞出来,即:

  • A ( x ) = ∑ i = 0 ∞ x 2 i = 1 1 − x 2 A(x) =\sum_{i=0}^{\infty}x^{2i}=\frac{1}{1-x^2} A(x)=i=0x2i=1x21
  • B ( x ) = 1 + x B(x)=1+x B(x)=1+x
  • C ( x ) = 1 + x + x 2 C(x)=1+x+x^2 C(x)=1+x+x2
  • D ( x ) = ∑ i = 0 ∞ x 2 i + 1 = x 1 − x 2 D(x)=\sum_{i=0}^{\infty}x^{2i+1}=\frac{x}{1-x^2} D(x)=i=0x2i+1=1x2x
  • E ( x ) = ∑ i = 0 ∞ x 4 i = 1 1 − x 4 E(x)=\sum_{i=0}^{\infty}x^{4i}=\frac{1}{1-x^4} E(x)=i=0x4i=1x41
  • F ( x ) = 1 + x + x 2 + x 3 F(x)=1+x+x^2+x^3 F(x)=1+x+x2+x3
  • G ( x ) = 1 + x G(x)=1+x G(x)=1+x
  • H ( x ) = ∑ i = 0 ∞ x 3 i = 1 1 − x 3 H(x)=\sum_{i=0}^{\infty}x^{3i}=\frac{1}{1-x^3} H(x)=i=0x3i=1x31

然后把它们乘起来,化个简,发现乘积是 x ( 1 − x ) 4 \frac{x}{(1-x)^4} (1x)4x

现在的目标就是,把这个式子展开,然后求指数为 n n n 时的系数。

泰勒展开

我们令 f ( x ) = x ( 1 − x ) 4 f(x)=\frac{x}{(1-x)^4} f(x)=(1x)4x,那把 f ( x ) f(x) f(x) 0 0 0 处展开,得:

f ( x ) = ∑ i = 0 ∞ f ( i ) ( 0 ) i ! x i f(x)=\sum_{i=0}^{\infty}\frac{f^{(i)}(0)}{i!}x^i f(x)=i=0i!f(i)(0)xi

那么第 n n n 项的系数就是 f ( n ) ( 0 ) n ! \frac{f^{(n)}(0)}{n!} n!f(n)(0),话句话说,我们需要求 x ( 1 − x ) 4 \frac{x}{(1-x)^4} (1x)4x 展开后在 x = 0 x=0 x=0 处的取值。

莱布尼茨公式

( u v ) ( n ) = ∑ i = 0 n ( n i ) u ( i ) v ( n − i ) (uv)^{(n)}=\sum_{i=0}^n\binom n iu^{(i)}v^{(n-i)} (uv)(n)=i=0n(in)u(i)v(ni)

我们令 u = x , v = ( 1 − x ) − 4 = ( x − 1 ) − 4 u=x,v=(1-x)^{-4}=(x-1)^{-4} u=x,v=(1x)4=(x1)4

发现只有当 i = 1 i=1 i=1 时,此时 u ′ = 1 u'=1 u=1(其它时候 u ( i ) = 0 u^{(i)}=0 u(i)=0),所以我们只需要求 v ( n − 1 ) v^{(n-1)} v(n1)

发现 v v v 是一个复合函数(即令 h ( x ) = x − 4 , g ( x ) = x − 1 h(x)=x^{-4},g(x)=x-1 h(x)=x4,g(x)=x1 的话, v = h ( g ( x ) ) v=h(g(x)) v=h(g(x))),那么有:

v ′ = h ′ ( g ( x ) ) g ′ ( x ) = h ′ ( g ( x ) ) v'=h'(g(x))g'(x)=h'(g(x)) v=h(g(x))g(x)=h(g(x))

那再求一次导,得到:

v ′ ′ = h ′ ′ ( g ( x ) ) g ′ ( x ) = h ′ ′ ( g ( x ) ) v''=h''(g(x))g'(x)=h''(g(x)) v=h(g(x))g(x)=h(g(x))

那照这个规律,第 ( n − 1 ) (n-1) (n1) 次求导之后,就可以得到:

v ( n − 1 ) = h ( n − 1 ) ( g ( x ) ) v^{(n-1)}=h^{(n-1)}(g(x)) v(n1)=h(n1)(g(x))

先把 h ( n − 1 ) ( x ) h^{(n-1)}(x) h(n1)(x) 搞出来,即:

h ( n − 1 ) ( x ) = ( x − 4 ) ( n − 1 ) = ( ∏ i = 0 n − 2 ( − 4 − i ) ) x − 4 − ( n − 1 ) = ( − 1 ) n − 1 ( n + 2 ) ! 6 x − n − 3 \begin{aligned} h^{(n-1)}(x)&=(x^{-4})^{(n-1)}\\ &=(\prod_{i=0}^{n-2}(-4-i))x^{-4-(n-1)}\\ &=(-1)^{n-1}\frac{(n+2)!}{6}x^{-n-3} \end{aligned} h(n1)(x)=(x4)(n1)=(i=0n2(4i))x4(n1)=(1)n16(n+2)!xn3

那么 h ( n − 1 ) ( g ( x ) ) = h ( n − 1 ) ( x − 1 ) = ( − 1 ) n − 1 ( n + 2 ) ! 6 ( x − 1 ) − n − 3 h^{(n-1)}(g(x))=h^{(n-1)}(x-1)=(-1)^{n-1}\frac{(n+2)!}{6}(x-1)^{-n-3} h(n1)(g(x))=h(n1)(x1)=(1)n16(n+2)!(x1)n3

由于我们需要的是这个式子在 x = 0 x=0 x=0 处的取值,那么:

h ( n − 1 ) ( g ( 0 ) ) = ( − 1 ) n − 1 ( n + 2 ) ! 6 ( − 1 ) − n − 3 = ( n + 2 ) ! 6 h^{(n-1)}(g(0))=(-1)^{n-1}\frac{(n+2)!}{6}(-1)^{-n-3}=\frac{(n+2)!}{6} h(n1)(g(0))=(1)n16(n+2)!(1)n3=6(n+2)!

然后乘个 n n n(因为 ( 1 n ) = n (^n_1)=n (1n)=n),再除个 n ! n! n!(看泰勒展开部分),得到:

a n s = n ( n + 1 ) ( n + 2 ) 6 ans=\frac{n(n+1)(n+2)}{6} ans=6n(n+1)(n+2)

那把 n n n 读进来直接算就可以了。


code

#include<cstdio>
#include<cctype> 
#include<cstring>
#include<algorithm>
#define P 10007
using namespace std;
const int inv6=1668;
int n=0;
int main(){
	char c=getchar();
	while(isdigit(c))  n=(n*10+(c^'0'))%P,c=getchar();
	printf("%d\n",1ll*n*(n+1)*(n+2)*inv6%P);
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值