欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

【BZOJ 3028】食物

程序员文章站 2024-03-21 17:37:10
...

传送门


problem

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

  • AA:偶数个
  • BB00 个或 11
  • CC:小于等于 22
  • DD:奇数个
  • EE44 的倍数个
  • FF00个,11 个,22 个或 33
  • GG:不超过一个
  • HH33 的倍数个

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

数据范围:n10500n\le10^{500}


solution

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

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

  • A(x)=i=0x2i=11x2A(x) =\sum_{i=0}^{\infty}x^{2i}=\frac{1}{1-x^2}
  • B(x)=1+xB(x)=1+x
  • C(x)=1+x+x2C(x)=1+x+x^2
  • D(x)=i=0x2i+1=x1x2D(x)=\sum_{i=0}^{\infty}x^{2i+1}=\frac{x}{1-x^2}
  • E(x)=i=0x4i=11x4E(x)=\sum_{i=0}^{\infty}x^{4i}=\frac{1}{1-x^4}
  • F(x)=1+x+x2+x3F(x)=1+x+x^2+x^3
  • G(x)=1+xG(x)=1+x
  • H(x)=i=0x3i=11x3H(x)=\sum_{i=0}^{\infty}x^{3i}=\frac{1}{1-x^3}

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

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

泰勒展开

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

f(x)=i=0f(i)(0)i!xif(x)=\sum_{i=0}^{\infty}\frac{f^{(i)}(0)}{i!}x^i

那么第 nn 项的系数就是 f(n)(0)n!\frac{f^{(n)}(0)}{n!}

莱布尼茨公式

(uv)(n)=i=0n(in)u(i)v(ni)(uv)^{(n)}=\sum_{i=0}^n(^n_i)u^{(i)}v^{(n-i)}

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

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

根据高阶导数的公式,即 (xa)(n)=(i=0n1(ai))xan(x^a)^{(n)}=(\prod_{i=0}^{n-1}(a-i))x^{a-n}

这个公式根据 (xa)=axa1(x^a)'=ax^{a-1} 化一化就可以推出来。

所以:

v(n1)=(1)n3(n+2)!6v^{(n-1)}=(-1)^{n-3}\frac{(n+2)!}{6}

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

ans=(1)n3n(n+1)(n+2)6ans=(-1)^{n-3}\frac{n(n+1)(n+2)}{6}

由于 (1)n3(-1)^{n-3} 只代表了第 nn 项的系数正负,不代表大小,可以直接忽略不计。

所以最终的答案就是:

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

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


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;
}
相关标签: 生成函数