# BZOJ5300 [CQOI2018]九连环 题解 | 高精度 FFT
今天做了传说中的CQOI六道板子题……有了一种自己很巨的错觉(雾
题面
求n连环的最少步数,n <= 1e5。
题解
首先……我不会玩九连环……
通过找规律(其实是百度搜索)可知,\(n\)连环的最少步数是\(\lfloor\frac{2^{n + 1}}{3}\rfloor\)。
(实际上,九连环的步骤恰好是一个叫【格雷码】的编码方式中的\(1\)一直到\(2^{n+1}-1\)!)
然后我们要输出这个\(\lfloor\frac{2^{n + 1}}{3}\rfloor\)就好了。
然后我们发现——毒瘤出题人让我们写高精度。
……那就只能写咯……
用FFT做高精度乘法,封装起来,然后正常进行快速幂即可。
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <iostream>
#define enter putchar('\n')
#define space putchar(' ')
using namespace std;
typedef long long ll;
template <class T>
void read(T &x){
    char c;
    bool op = 0;
    while(c = getchar(), c < '0' || c > '9')
    if(c == '-') op = 1;
    x = c - '0';
    while(c = getchar(), c >= '0' && c <= '9')
    x = x * 10 + c - '0';
    if(op == 1) x = -x;
}
template <class T>
void write(T x){
    if(x < 0) putchar('-'), x = -x;
    if(x >= 10) write(x / 10);
    putchar('0' + x % 10);
}
const int N = 150000;
const double PI = acos(-1);
int T, x;
struct cp {
    double a, b;
    cp(){}
    cp(double x, double y): a(x), b(y){}
    cp operator + (const cp &obj) const {
	return cp(a + obj.a, b + obj.b);
    }
    cp operator - (const cp &obj) const {
	return cp(a - obj.a, b - obj.b);
    }
    cp operator * (const cp &obj) const {
	return cp(a * obj.a - b * obj.b, a * obj.b + b * obj.a);
    }
} inv[N], omg[N];
void init(int n){
    for(int i = 0; i < n; i++){
	omg[i] = cp(cos(2 * PI / n * i), sin(2 * PI / n * i));
	inv[i] = cp(omg[i].a, -omg[i].b);
    }
}
void fft(cp *a, int n, cp *omg){
    int lim = 0;
    while((1 << lim) < n) lim++;
    for(int i = 0; i < n; i++){
	int t = 0;
	for(int j = 0; j < lim; j++)
	    if(i >> j & 1) t |= 1 << (lim - j - 1);
	if(i < t) swap(a[i], a[t]);
    }
    for(int l = 2; l <= n; l <<= 1){
	int m = l / 2;
	for(cp *p = a; p != a + n; p += l)
	    for(int i = 0; i < m; i++){
		cp t = omg[n / l * i] * p[i + m];
		p[i + m] = p[i] - t;
		p[i] = p[i] + t;
	    }
    }
}
struct big {
    int g[N], len;
    big(){
	memset(g, 0, sizeof(g));
	len = 1;
    }
    big(int x){
	memset(g, 0, sizeof(g));
	len = 0;
	if(!x){
	    len = 1;
	    return;
	}
	while(x) g[len++] = x % 10, x /= 10;
    }
    void out(){
	for(int i = len - 1; i >= 0; i--)
	    printf("%d", g[i]);
	enter;
    }
    void operator /= (int x){
	int sum = 0, newlen = 0;
	for(int i = len - 1; i >= 0; i--){
	    sum = sum * 10 + g[i];
	    if(sum < x) g[i] = 0;
	    else{
		if(!newlen) newlen = i + 1;
		g[i] = sum / x;
		sum %= x;
	    }
	}
	len = max(newlen, 1);
    }
    void operator *= (const big &b){
	static cp A[N], B[N];
	int newlen = len + b.len - 1, n = 1;
	while(n < newlen) n <<= 1;
	for(int i = 0; i < n; i++){
	    A[i] = cp(i < len ? g[i] : 0, 0);
	    B[i] = cp(i < b.len ? b.g[i] : 0, 0);
	}
	init(n);
	fft(A, n, omg);
	fft(B, n, omg);
	for(int i = 0; i < n; i++)
	    A[i] = A[i] * B[i];
	fft(A, n, inv);
	for(int i = 0; i < newlen; i++)
	    g[i] = (int)floor(A[i].a / n + 0.5);
	g[len = newlen] = 0;
	for(int i = 0; i < len; i++)
	    g[i + 1] += g[i] / 10, g[i] %= 10;
	if(g[len]) len++;
    }
} ret, a;
int main(){
    read(T);
    while(T--){
	read(x), x++;
	ret = big(1), a = big(2);
	while(x){
	    if(x & 1) ret *= a;
	    a *= a;
	    x >>= 1;
	}
	ret /= 3;
	ret.out();
    }
    return 0;
}
# BZOJ5300 [CQOI2018]九连环 题解 | 高精度 FFT的更多相关文章
- 【BZOJ5300】[CQOI2018]九连环 (高精度,FFT)
		[BZOJ5300][CQOI2018]九连环 (高精度,FFT) 题面 BZOJ 洛谷 题解 去这里看吧,多么好 #include<iostream> #include<cstdi ... 
- BZOJ5300:[CQOI2018]九连环——题解
		一种打表的方法,适用于知道如何解九连环的人. 我们知道,解九(n)连环必须先解第九(n)环,然后解八(n-1).七(n-2)-- 根据这个我们飞快的写出了一个递推式,设\(f[i]\)为\(i\)连环 ... 
- BZOJ5300 [Cqoi2018]九连环 【数学】【FFT】
		题目分析: 这道题是数学必修五的原题,做法如下图,书上讲得很详细了. 那么这道题目用快速幂就可以解决了,值得注意的是,分析时间复杂度会发现直接做乘法其实是O(n^2)的,但是有一个1/20左右的常数, ... 
- 2019.01.02 bzoj5300: [Cqoi2018]九连环(fft优化高精+快速幂)
		传送门 题意不好描述(自己看样例解释) 首先可以推出一个递推式:fn=fn−1+2fn−2+1f_n=f_{n-1}+2f_{n-2}+1fn=fn−1+2fn−2+1 然后可以构造两个等式: ... 
- BZOJ5300 [Cqoi2018]九连环  【dp + 高精】
		题目链接 BZOJ5300 题解 这题真的是很丧病,,卡高精卡到哭 我们设\(f[i]\)表示卸掉前\(i\)个环需要的步数 那么 \[f[i] = 2*f[i - 2] + f[i - 1] + 1 ... 
- CQOI2018 九连环 打表找规律 fft快速傅里叶变换
		题面: CQOI2018九连环 分析: 个人认为这道题没有什么价值,纯粹是为了考算法而考算法. 对于小数据我们可以直接爆搜打表,打表出来我们可以观察规律. f[1~10]: 1 2 5 10 21 4 ... 
- CQOI2018简要题解
		CQOI2018简要题解 D1T1 破解 D-H 协议 题意 Diffie-Hellman 密钥交换协议是一种简单有效的密钥交换方法.它可以让通讯双方在没有事先约定密钥(密码)的情况下,通过不安全的信 ... 
- 高精度&&FFT
		ACM-高精度模板(综合篇) 时间:-- :: 阅读: 评论: 收藏: [点我收藏+] 标签:高精度 在这里,我们约定,能用int表示的数据视为单精度,否则为高精度.所有函数的设计均采用带返回值的形式 ... 
- CQOI2018 简要题解
		破解D-H协议 列个式子会发现是BSGSBSGSBSGS的模板题,直接码就是了. 代码: #include<bits/stdc++.h> #include<tr1/unordered ... 
随机推荐
- 计算几何总结(Part 1~2)
			Preface 对于一个初三连三角函数都不会的蒟蒻来说计算几何简直就是噩梦. 反正都是要学的也TM没办法,那就慢慢一点点学起吧. 计算几何要有正确的板子,不然那种几百行CODE的题写死你. 本蒟蒻的学 ... 
- [spark][python]Spark map 处理
			map 就是对一个RDD的各个元素都施加处理,得到一个新的RDD 的过程 [training@localhost ~]$ cat names.txtYear,First Name,County,Sex ... 
- JDK8漫谈——集合更强大
			解决什么问题 集合计算不足 解决重复代码 背后思想 管道 封装 数据处理 内容说明 是什么 计算担当.集合用于数据存储,流用于数据计算,不会修改原始数据 内置循环.高级迭代器,内置循环和计算 单向.数 ... 
- Nginx反向代理的简单实现
			1)nginx的反向代理:proxy_pass2)nginx的负载均衡:upstream 下面是nginx的反向代理和负载均衡的实例: 负载机:A机器:103.110.186.8/192.168.1. ... 
- WIFI探针技术
			1.WIFI 探针定义 WIFI 探针是一种能够主动识别 Android 和 IOS 设备,感知用户行为轨迹的精准数据收集前端,基于 WIFI探测技术.移动互联网和云计算等先进技术自动识别探针附近的智 ... 
- Android 學習之旅!(1)
			就這樣就過去了一年加一個學期,現在是大二第二個學期而且是下半學期了,以前都是無所事事,沒事睡睡覺,打打遊戲就過去了,但是想到家境和以後的路,我還是決心自己找點東西學習下,以後出去還能有一技之長(雖然可 ... 
- [2017BUAA软工]第0次作业
			第0次作业 Part 1:结缘计算机 1. 你为什么选择计算机专业?你认为你的条件如何?和这些博主比呢? 我跟这篇博客中的作者相似的地方在于,我们都在一个比较早的阶段接触了计算机,我家乡的经济在全国来 ... 
- Java并发—synchronized关键字
			synchronized关键字的作用是线程同步,而线程的同步是为了防止多个线程访问一个数据对象时,对数据造成的破坏. synchronized用法 1. 在需要同步的方法的方法签名中加入synchro ... 
- phpstorm 注释模板
			/** * Created by ${PRODUCT_NAME}. * User: ${USER} * Date: ${DATE} * Time: ${TIME} */ 
- RocketMQ事务消息实战
			我们以一个订单流转流程来举例,例如订单子系统创建订单,需要将订单数据下发到其他子系统(与第三方系统对接)这个场景,我们通常会将两个系统进行解耦,不直接使用服务调用的方式进行交互.其业务实现步骤通常为: ... 
