【BZOJ3028】食物(生成函数基础题)

点此看题面

大致题意: 给定你若干物品的数量要求(题解里有,这里省略),求选出(n)个物品的方案数。

前言

无意中刷到这道生成函数基础题。(生成函数可见这篇博客:初学生成函数(一)——普通生成函数

上次【洛谷2000】拯救世界因为要高精结果没写坑掉了,这次一看不用高精就来水一发。

生成函数

考虑搞出每种物品的生成函数。

承德汉堡(偶数个):(x^0+x^2+x^4+...=frac1{1-x^2})

可乐((0)个或(1)个):(x^0+x^1=frac {1-x^2}{1-x})

鸡腿((0)个,(1)个或(2)个):(x^0+x^1+x^2=frac{1-x^3}{1-x})

蜜桃多(奇数个):(x^1+x^3+x^5+...=frac x{1-x^2})

鸡块((4)的倍数个):(x^0+x^4+x^8+...=frac1{1-x^4})

包子((0)个,(1)个,(2)个或(3)个):(x^0+x^1+x^2+x^3=frac{1-x^4}{1-x})

土豆片炒肉(不超过一个):(x^0+x^1=frac{1-x^2}{1-x})

面包((3)的倍数个):(x^0+x^3+x^6+...=frac1{1-x^3})

然后把这些东西全部乘在一起并约分(这一过程省略,相信大家都会)得到:

[frac x{(1-x)^4} ]

处理询问

询问问的是选出(n)个物品的方案数,也就是生成函数(n)次项的系数。

考虑该生成函数就等于(x(frac1{1-x})^4)

由于(frac1{1-x}=sum_{i=0}^{infty}x^i),所以如果我们去掉(x)这一项,那就相当于求((sum_{i=0}^{infty}x^i)^4)(n-1)项的次数。

也就是把(n-1)个格子划分为(4)部分(每一部分可以为空)的方案数,那么用隔板法,一共有(n)个间隔和(3)个板,方案数就是:

[C_{n+2}^3 ]

对于读入我们直接读入字符串,然后转化为(int)时同时取模,这样就可以避免高精了。

代码

#include<bits/stdc++.h>
#define Tp template<typename Ty>
#define Ts template<typename Ty,typename... Ar>
#define Reg register
#define RI Reg int
#define Con const
#define CI Con int&
#define I inline
#define W while
#define LEN 500
#define X 10007
using namespace std;
int n;char s[LEN+5];
int main()
{
	RI i,l;for(scanf("%s",s+1),i=1,l=strlen(s+1);i<=l;++i) n=((n<<3)+(n<<1)+(s[i]&15))%X;//转化过程中同时取模
	return printf("%d",(1LL*(n+2)*(n+1)*n/6)%X),0;//输出C(n+2,3)
}
原文地址:https://www.cnblogs.com/chenxiaoran666/p/BZOJ3028.html