Luogu 2000 拯救世界
从胡小兔的博客那里过来的,简单记一下生成函数。
生成函数
数列$\{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 拯救世界的更多相关文章
- luogu P2000 拯救世界
嘟嘟嘟 题目有点坑,要你求的多少大阵指的是召唤kkk的大阵数 * lzn的大阵数,不是相加. 看到这个限制条件,显然要用生成函数推一推. 比如第一个条件"金神石的块数必须是6的倍数" ...
- luogu P2000 拯救世界 生成函数_麦克劳林展开_python
模板题. 将所有的多项式按等比数列求和公式将生成函数压缩,相乘后麦克劳林展开即可. Code: n=int(input()) print((n+1)*(n+2)*(n+3)*(n+4)//24)
- [题解] Luogu P2000 拯救世界
生成函数板子题...... 要写高精,还要NTT优化......异常dl 这个并不难想啊...... 一次召唤会涉及到\(10\)个因素,全部写出来,然后乘起来就得到了答案的生成函数,输出\(n\)次 ...
- 洛谷P2000 拯救世界(生成函数)
题面 题目链接 Sol 生成函数入门题 至多为\(k\)就是\(\frac{1-x^{k+1}}{1-x}\) \(k\)的倍数就是\(\frac{1}{1-x^k}\) 化简完了就只剩下一个\(\f ...
- 【洛谷】P2000 拯救世界
题解 小迪的blog : https://www.cnblogs.com/RabbitHu/p/9178645.html 请大家点推荐并在sigongzi的评论下面点支持谢谢! 掌握了小迪生成函数的有 ...
- 清北学堂模拟赛d7t6 拯救世界
分析:如果题目中没有环的话就是一道裸的最长路的题目,一旦有环每个城市就会被救多次火了.把有向有环图变成有向无环图只需要tarjan一边就可以了. #include <bits/stdc++.h& ...
- [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^ ...
- Luogu2000 拯救世界
题目链接:戳我 生成函数的入门题吧. 我们可以把条件限制转化为生成函数,然后用第i项的系数来表示一共使用n块石头的方案个数. (你问我为什么?你可以自己演算一下,或者去看大佬的博客-->这里面讲 ...
- [洛谷P2000 拯救世界]
生成函数版题. 考虑对于这些条件写出\(OGF\) \(1 + x^6 + x^{12} + x^{18}..... = \frac{1}{1 - x^6}\) \(1 + x + x ^ 2 + x ...
随机推荐
- VG 859使用
1.基本使用: 1) FUNC 0-9可以直接切换 FUNC A-F 需要+SHIF,切换方法为: FUNC->SHIFT->A-F 2) FORMAT->TIMING 连续按T ...
- 关于FPGA电源精度要求
FPGA对DC-DC精度的要求不断提升 FPGA厂商不断采用更先进的工艺来降低器件功耗,提高性能,同时FPGA对供电电源的精度要求也越加苛刻,电压必须维持在非常严格的容限内,如果供电电压范围超出了规范 ...
- kotlin学习二:初步认识kotlin
1. 函数 kotlin中支持顶级函数(文件内直接定义函数),对比JAVA来说,JAVA的程序入口是main方法,kotlin也一样,入口为main函数 首先看下kotlin中main函数的定义. f ...
- Centos6-7安装Python3.5
可以看到我们现在是2.7.5的,现在我安装一个3.5版本的 安装python3之前首先安装ssl开发库,否则会造成python3的ssl库都无法使用!!! yum install openssl op ...
- http 和 https 区别?
1. HTTP 的URL 以http:// 开头,而HTTPS 的URL 以https:// 开头2. HTTP 是不安全的,而 HTTPS 是安全的3. HTTP 标准端口是80 ,而 HTTPS ...
- TCP/IP协议:最大传输单元MTU 和 最大分节大小MSS
MTU = MSS + TCP Header + IP Header. mtu是网络传输最大报文包. mss是网络传输数据最大值. MTU:maximum transmission unit,最大传输 ...
- node的调试
/* * 在node中,提供了一个可以通过简单TCP协议来访问的调试器.可以使用node debug 文件名,当调试器可以使用之后,命令行窗口界面中出现一个debugger命令提示符.后跟ok文字.代 ...
- Oralce OMF 功能详解
OMF,全称是Oracle_Managed Files,即Oracle文件管理,使用OMF可以简化管理员的管理工作,不用指定文件的名字.大小.路径,其名字,大小, 路径由oracle 自动分配.在删除 ...
- 在VritualBox中安装CentOS7
系统:Windows10 位 详细步骤参考: Windows平台上通过VirtualBox安装centos虚拟机 安装virtual box 出现2503错误解决:c:/windows/temp 添加 ...
- [Z] Shell中脚本变量和函数变量的作用域
在shell中定义函数可以使代码模块化,便于复用代码.不过脚本本身的变量和函数的变量的作用域问题可能令你费解,在这里梳理一下这个问题. (1)Shell脚本中定义的变量是global的,其作用域从被定 ...