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

生成函数

数列$\{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. 贴一段demo代码,演示channel之间的同步

    package main import ( "fmt" "time" ) func deskGoRoutine(index int, userChannel c ...

  2. Linux c- libevent

    libevent是一个事件触发的网络库,适用于windows.linux.bsd等多种平台,内部使用select.epoll.kqueue等系统调用管理事件机制.著名分布式缓存软件memcached也 ...

  3. TMS320CC657基本外围电路调试

    一.本文内容 本文主要包含以下三个基本外围电路的调试过程与调试结果: 电源模块 时钟模块 复位模块 二.电源模块调试 无论对FPGA还是DSP而言,对电源的上电顺序都有一定的要求,且不同型号的器件对电 ...

  4. spring cache之自定义keys的过期时间

    spring @cacheable注解默认不支持方法级别的缓存失效时间,只能通过配置来配置全局的失效时间 如果需要实现对方法级别的缓存支持失效时间机制,有一种比较简单的方法,spring配置文件如下: ...

  5. 003:MySQL账号创建授权以及Workbench

    目录 一. 权限管理 1."用户 + IP"的概念 2. 用户权限管理 3. 基本操作 4. 撤销权限 5.授权和创建用户 二. MySQL模拟角色 三. Workbench与Ut ...

  6. [CSAPP] Chapter 1 Overview of Computer

    1.1 information is bits + context All computer programs are just a sequence of bits, each with a val ...

  7. 如何利用R包qqman画曼哈顿图?

    如何利用R包qqman画曼哈顿图? 2017-07-10 lili 生信人 众多周知,R语言提供了各种各样的包,方便实现我们的目的,下面给大家介绍一个可以便捷的画曼哈顿图的包:qqman instal ...

  8. C++ primer plus

    给cout指针,默认打印指针地址,但如果指针的类型的char*,将打印指向的字符串,如果要显示的是字符串的地址,将指针强制转换为另一种类型 char* animal cout << ani ...

  9. Java--神奇的hashcode

    一.Object的HashCode定义 public native int hashCode(); Object类的hashCode方式使用了native修饰也就意味着真正的实现调用的其他语言编写的方 ...

  10. Nginx 安装与使用

    作者:吴秦出处:http://www.cnblogs.com/skynet/ 前言 nginx Nginx ("engine x") 是一个高性能的HTTP和反向代理服务器,也是一 ...