胡小兔的博客那里过来的,简单记一下生成函数。

生成函数

数列$\{1, 1, 1, 1, \cdots\}$的生成函数是$f(x) = 1 + x + x^2 + x^3 + \cdots$,根据等比数列求和公式,可以得到$f(x) = \frac{1}{1 - x}$。

把两边分别平方,得到

$$\frac{1}{(1 - x)^2} = (1 + x + x^2 + x^3 + x^4 + \cdots)^2 = 1 + 2x + 3x^2 + 4x^3 + \cdots$$

相当于数列$\{1, 2, 3, 4, 5, \cdots \}$的生成函数。

两边三次方,得到

$$\frac{1}{(1 - x)^3} = 1 + 3x + 6x^2 + 10x^3 + \cdots$$

发现数列$\sum_{i = 0}^{\infty}\binom{i + k - 1}{k - 1}x^i$的生成函数是$\frac{1}{(1 - x)^k}$。

而数列$\sum_{i = 0}^{\infty}x^i[i \mod k == 0]$的生成函数是$\frac{1}{1 - x^k}$。

本题解法

把限制条件看成数列,第一个限制条件相当于数列$\{1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, \cdots \}$,而第二个限制条件则相当于有限长数列$\{1, 1, 1, 1, 1, 1, 1, 1, 1\}$,……,所有的限制条件都可以这样子类推出来。

把这个数列写成生成函数,第个限制条件的第$i$项系数可以看成是这一项取$i$个的方法,把这十个生成函数乘起来之后得到的生成函数的第$i$项就相当于一共取了$i$项的方案数。

最后乘起来得到了$\frac{1}{(1 - x)^5}$,对应了数列$\sum_{i = 0}^{\infty}\binom{i + 4}{4}x^i$的第$n$项,即$\frac{(n + 1)(n + 2)(n + 3)(n + 4)}{24}$。

然后就是一个高精了,因为$n$的位数很多,所以乘法的时候需要写$fft$。

Code:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <cmath>
using namespace std;
typedef double db; const int N = 2e6 + ;
const db Pi = acos(-1.0); int lim, pos[N];
char str[N]; struct Cpx {
db x, y; inline Cpx (db _x = , db _y = ) {
x = _x, y = _y;
} friend Cpx operator + (const Cpx u, const Cpx v) {
return Cpx(u.x + v.x, u.y + v.y);
} friend Cpx operator - (const Cpx u, const Cpx v) {
return Cpx(u.x - v.x, u.y - v.y);
} friend Cpx operator * (const Cpx u, const Cpx v) {
return Cpx(u.x * v.x - u.y * v.y, u.x * v.y + v.x * u.y);
} } a[N], b[N]; inline void prework(int len) {
int l = ;
for (lim = ; lim < len; lim <<= , ++l);
for (int i = ; i < lim; i++)
pos[i] = (pos[i >> ] >> ) | ((i & ) << (l - ));
} inline void fft(Cpx *c, int opt) {
for (int i = ; i < lim; i++)
if (i < pos[i]) swap(c[i], c[pos[i]]);
for (int i = ; i < lim; i <<= ) {
Cpx wn(cos(Pi / i), opt * sin(Pi / i));
for (int len = i << , j = ; j < lim; j += len) {
Cpx w(, );
for (int k = ; k < i; k++, w = w * wn) {
Cpx x = c[j + k], y = w * c[j + k + i];
c[j + k] = x + y, c[j + k + i] = x - y;
}
}
}
} struct BigInt {
int len, s[N]; inline void init() {
len = ;
memset(s, , sizeof(s));
} inline void readIn() {
scanf("%s", str);
len = strlen(str);
for (int i = ; i < len; i++) s[i] = str[len - i - ] - '';
} inline void print() {
if (!len) putchar('');
else {
for (int i = len - ; i >= ; i--) printf("%d", s[i]);
}
printf("\n");
} friend BigInt operator + (const BigInt &x, const int &y) {
BigInt res = x;
res.s[] += y;
for (int i = ; i < res.len; i++) {
if (i == res.len - ) {
if (res.s[i] >= ) ++res.len;
else break;
}
res.s[i + ] += res.s[i] / , res.s[i] %= ;
}
for (; res.s[res.len - ] == && res.len > ; --res.len);
return res;
} friend BigInt operator * (const BigInt &x, const BigInt &y) {
prework(x.len + y.len - );
for (int i = ; i < lim; i++) a[i] = b[i] = Cpx(, );
for (int i = ; i < x.len; i++) a[i].x = x.s[i];
for (int i = ; i < y.len; i++) b[i].x = y.s[i];
fft(a, ), fft(b, );
for (int i = ; i < lim; i++) a[i] = a[i] * b[i];
fft(a, -); BigInt res;
res.init();
res.len = x.len + y.len - ;
for (int i = ; i < res.len; i++) res.s[i] = int(a[i].x / lim + 0.5); for (int i = ; i < res.len; i++) {
if (i == res.len - ) {
if (res.s[i] >= ) ++res.len;
else break;
}
res.s[i + ] += res.s[i] / , res.s[i] %= ;
}
for (; res.s[res.len - ] == && res.len > ; --res.len); return res;
} friend BigInt operator / (const BigInt &x, const int y) {
BigInt res;
res.init();
int rest = ;
for (int i = x.len - ; i >= ; i--) {
rest = rest * + x.s[i];
if (rest >= y) res.s[res.len++] = rest / y, rest %= y;
else if (res.len) res.s[res.len++] = ;
}
for (int i = ; i < res.len / ; i++) swap(res.s[i], res.s[res.len - - i]);
return res;
} } n; int main() {
#ifndef ONLINE_JUDGE
freopen("Sample.txt", "r", stdin);
#endif n.readIn();
// n.print(); BigInt n1 = n + , n2 = n + , n3 = n + , n4 = n + ;
// n1.print(), n2.print(), n3.print(), n4.print(); BigInt ans = n1 * n2 * n3 * n4;
// ans.print(); ans = ans / ;
ans.print();
return ;
}

Luogu 2000 拯救世界的更多相关文章

  1. luogu P2000 拯救世界

    嘟嘟嘟 题目有点坑,要你求的多少大阵指的是召唤kkk的大阵数 * lzn的大阵数,不是相加. 看到这个限制条件,显然要用生成函数推一推. 比如第一个条件"金神石的块数必须是6的倍数" ...

  2. luogu P2000 拯救世界 生成函数_麦克劳林展开_python

    模板题. 将所有的多项式按等比数列求和公式将生成函数压缩,相乘后麦克劳林展开即可. Code: n=int(input()) print((n+1)*(n+2)*(n+3)*(n+4)//24)

  3. [题解] Luogu P2000 拯救世界

    生成函数板子题...... 要写高精,还要NTT优化......异常dl 这个并不难想啊...... 一次召唤会涉及到\(10\)个因素,全部写出来,然后乘起来就得到了答案的生成函数,输出\(n\)次 ...

  4. 洛谷P2000 拯救世界(生成函数)

    题面 题目链接 Sol 生成函数入门题 至多为\(k\)就是\(\frac{1-x^{k+1}}{1-x}\) \(k\)的倍数就是\(\frac{1}{1-x^k}\) 化简完了就只剩下一个\(\f ...

  5. 【洛谷】P2000 拯救世界

    题解 小迪的blog : https://www.cnblogs.com/RabbitHu/p/9178645.html 请大家点推荐并在sigongzi的评论下面点支持谢谢! 掌握了小迪生成函数的有 ...

  6. 清北学堂模拟赛d7t6 拯救世界

    分析:如果题目中没有环的话就是一道裸的最长路的题目,一旦有环每个城市就会被救多次火了.把有向有环图变成有向无环图只需要tarjan一边就可以了. #include <bits/stdc++.h& ...

  7. [LGP2000] 拯救世界

    6的倍数 1/(1-x^6) 最多9块 (1-x^10)/(1-x) 最多5块 (1-x^6)/(1-x) 4的倍数 1/(1-x^4) 最多7块 (1-x^8)/(1-x) 2的倍数 1/(1-x^ ...

  8. Luogu2000 拯救世界

    题目链接:戳我 生成函数的入门题吧. 我们可以把条件限制转化为生成函数,然后用第i项的系数来表示一共使用n块石头的方案个数. (你问我为什么?你可以自己演算一下,或者去看大佬的博客-->这里面讲 ...

  9. [洛谷P2000 拯救世界]

    生成函数版题. 考虑对于这些条件写出\(OGF\) \(1 + x^6 + x^{12} + x^{18}..... = \frac{1}{1 - x^6}\) \(1 + x + x ^ 2 + x ...

随机推荐

  1. 利用反射及ActionFilterAttribute实现MVC权限管理

    1.利用反射获取当前程序集下的所有控制器和方法,拼接后写入到数据库. public void GetRightInfo() { ; var controllerTypes = Assembly.Get ...

  2. bzoj4764: 弹飞大爷

    Description 自从WC退役以来,大爷是越来越懒惰了.为了帮助他活动筋骨,也是受到了弹飞绵羊一题的启发,机房的小伙伴们 决定齐心合力构造一个下面这样的序列.这个序列共有N项,每项都代表了一个小 ...

  3. Java 代码块

    一.简介 1.普通代码块: 类中方法的方法体 2.构造代码块: 构造块会在创建对象时被调用,每次创建时都会被调用,优先于类构造函数执行. 3.静态代码块: 用static{}包裹起来的代码片段,只会执 ...

  4. Android中preference标签的使用

    现在做公司任务的时候,经常会要去读Settings的源码,然后发现在xml文件中几乎全是用的preferenceScreen和preferenceCategory标签,很少有用布局和控件的,然后我就自 ...

  5. ECMAScript有6种继承方式(实现继承)

    本人对于ECMAScript继承机制有些见解,如果说的不对,敬请赐教~~~~ 继承是OO语言(面向对象)挺好的概念,许多OO语言都支持两种继承方式(接口只继承方法签名.实际继承则继承实际的方法),但是 ...

  6. SVN专题(Visual SVN Server + TortoiseSVN + Visual SVN)

    参考资料: 1.Windows环境下搭建SVN服务器.原文地址:https://blog.csdn.net/lu1024188315/article/details/74082227 2.Git|SV ...

  7. nginx代理socket tcp/udp

    准备一台linux服务器.nginx官网:http://nginx.org/ .在网上搜到大致用的是 ngx_stream_core_module 这个模块,这里你也可以关注一下官方文档中的其他模块都 ...

  8. Oracle11gr2_ADG管理之switchover补充

    之前演示的switchver总是提示下面的错误,并且需要人工干预: Oracle11gr2_ADG管理之switchover实战 DGMGRL> switchover to snewtest; ...

  9. 给虚拟机添加eth1网络适配器(网卡)

    1.虚拟机 -- > 设置 2.添加 --> 网络适配器 --> 下一步 3.主机 -- > 完成 -- > 确定 4.修改网卡的配置文件 cd /etc/sysconf ...

  10. AngularJS的 $resource服务 关于CRUD操作

    AngularJs 的CRUD 操作 是指对数据库的操作: CRUD其实是数据库基本操作中的Create(创建).ReadRetrieve(读取).Update(更新).Delete(删除).而这里的 ...