数论:生成函数
生成函数
1. 定义
任意给一个无穷序列
可以发现,生成函数其实是一种映射。
然后,这里就可以变为与多项式有关的东西(FFT、NTT 警告)。
还有各种之类的高等数学,这里就不展开了。
2. 应用
一)砝码拼凑
给定三个砝码,重量分别为
a,b,c g,然后再给定需要拼凑的重量n ,问有多少种方案。
这里,我们首先可以用三个序列来分别表示三个砝码能表示的重量的方案。
以
同理,
我们发现,如果将这三个的函数相乘的话,其实就是我们的砝码的表示方案。
简单的证明一下:我们以前计算使用的乘法原理,其实就是我们新的多项式相乘。加法原理,其实就是新的同类项合并。
那么,将三个函数(就是多项式)相乘,就可以得到最终的方案的表示。
2)砝码拼凑(加强版)
给定三种砝码,重量分别为
a_i g,每一种砝码可以取x_i 个(x_i=0 表示可以无穷取),然后再给定需要拼凑的重量n ,问有多少种方案。
首先,我们看:1 g 的可以取 2 个,生成函数是什么。
对应的序列应该就是
我们再来看:2 g 的可以取无限个,生成函数是什么。
对应的序列就是
相乘,每一项就是方案数。
3)取苹果
有
n 种不同的苹果,每种有无限个,现在要取k 个,问方案数。
我们可以使用隔板法求,但不是今天的重点。
我们考虑对于每一个苹果来说,生成函数都是
那么,总的生成函数就是
具体怎么展开,我们暂且不讲,需要使用可以自行百度其实是我不会。
3. 例题
T1:食物
题目传送门 AcWing
这就是一个简单的生成函数。
经过一通推导,可以得到:
下面的可以展开(鬼知道怎么展开):
那么,我们就可以直接计算了,答案就是
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
typedef long long ll;
const int N = 505, Mod = 1e4 + 7;
char str[N];
int main()
{
cin >> (str + 1);
ll n = 0;
for (int i = 1; i <= (int)strlen(str + 1); ++ i) n = (n * 10 + str[i] - '0') % Mod;
cout << n * (n + 1) * (n + 2) / 6 % Mod << endl;
return 0;
}