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 ...
随机推荐
- 利用反射及ActionFilterAttribute实现MVC权限管理
1.利用反射获取当前程序集下的所有控制器和方法,拼接后写入到数据库. public void GetRightInfo() { ; var controllerTypes = Assembly.Get ...
- bzoj4764: 弹飞大爷
Description 自从WC退役以来,大爷是越来越懒惰了.为了帮助他活动筋骨,也是受到了弹飞绵羊一题的启发,机房的小伙伴们 决定齐心合力构造一个下面这样的序列.这个序列共有N项,每项都代表了一个小 ...
- Java 代码块
一.简介 1.普通代码块: 类中方法的方法体 2.构造代码块: 构造块会在创建对象时被调用,每次创建时都会被调用,优先于类构造函数执行. 3.静态代码块: 用static{}包裹起来的代码片段,只会执 ...
- Android中preference标签的使用
现在做公司任务的时候,经常会要去读Settings的源码,然后发现在xml文件中几乎全是用的preferenceScreen和preferenceCategory标签,很少有用布局和控件的,然后我就自 ...
- ECMAScript有6种继承方式(实现继承)
本人对于ECMAScript继承机制有些见解,如果说的不对,敬请赐教~~~~ 继承是OO语言(面向对象)挺好的概念,许多OO语言都支持两种继承方式(接口只继承方法签名.实际继承则继承实际的方法),但是 ...
- SVN专题(Visual SVN Server + TortoiseSVN + Visual SVN)
参考资料: 1.Windows环境下搭建SVN服务器.原文地址:https://blog.csdn.net/lu1024188315/article/details/74082227 2.Git|SV ...
- nginx代理socket tcp/udp
准备一台linux服务器.nginx官网:http://nginx.org/ .在网上搜到大致用的是 ngx_stream_core_module 这个模块,这里你也可以关注一下官方文档中的其他模块都 ...
- Oracle11gr2_ADG管理之switchover补充
之前演示的switchver总是提示下面的错误,并且需要人工干预: Oracle11gr2_ADG管理之switchover实战 DGMGRL> switchover to snewtest; ...
- 给虚拟机添加eth1网络适配器(网卡)
1.虚拟机 -- > 设置 2.添加 --> 网络适配器 --> 下一步 3.主机 -- > 完成 -- > 确定 4.修改网卡的配置文件 cd /etc/sysconf ...
- AngularJS的 $resource服务 关于CRUD操作
AngularJs 的CRUD 操作 是指对数据库的操作: CRUD其实是数据库基本操作中的Create(创建).ReadRetrieve(读取).Update(更新).Delete(删除).而这里的 ...