0x02 基本算法-枚举、模拟、递推
递归实现指数型枚举
int _, n, m, k, x, y;
vector<int> vec;
void calc(int x) {
if (x == n + 1) {
for (int i = 0; i < vec.size(); ++i) cout << vec[i] << " ";
cout << "\n"; // 注意一下,以后输出回车用 "\n" 而不是 endl
return;
}
calc(x + 1), vec.push_back(x);
calc(x + 1), vec.pop_back();
}
int main() {
ios_base::sync_with_stdio(false), cin.tie(0);
cin >> n;
calc(1);
}
递归实现组合型枚举
int n, m;
vector<int> vec;
void calc(int x) {
// 剪枝,如果已经选取了超过m个数,
// 或者即使选上剩下所有数也不够m个就要提前结束搜索了 ↓
if (vec.size() > m || vec.size() + (n - x + 1) < m) return;
if (x == n + 1) {
for (int i = 0; i < vec.size(); ++i) cout << vec[i] << " ";
cout << "\n"; // 注意一下,以后输出回车用 "\n" 而不是 endl
return;
}
calc(x + 1), vec.push_back(x);
calc(x + 1), vec.pop_back();
}
int main() {
ios_base::sync_with_stdio(false), cin.tie(0);
cin >> n >> m;
calc(1);
}
递归实现排列型枚举
int n, m;
int order[20];
bool chosen[20];
void cal(int k) {
if (k == n + 1) {
for(int i = 1;i<=n;++i)
cout << order[i] << " ";
cout << endl; return;
}
for (int i = 1;i <= n; ++i) {
if (chosen[i])continue;
chosen[i] = true;
order[k] = i;
cal(k + 1);
chosen[i] = false;
}
}
int main() {
ios::sync_with_stdio(false), cin.tie(0);
cin >> n;cal(1);
}
费解的开关
const int N = 6;//因为后续操作读取的是字符串
char g[N][N];
char backup[N][N];//备份 --- 用于记录每次枚举第1行的情况
int n;
int dx[5] = {-1,0,1,0,0}, dy[5] = {0,0,0,-1,1};//用于表示当前位置及该位置的上下左右位置的偏移量
//改变当前灯及其上下左右灯的状况
void turn(int x, int y){
for(int i = 0; i < 5; i ++){
int a = x + dx[i], b = y + dy[i];//用于表示当前位置或该位置的上下左右位置
if(a >= 0 && a < 5 || b >= 0 && b < 5){
g[a][b] ^= 1;//用于'0' 和'1'的相互转换 -----根据二者的Ascll码值特点
}
}
}
int main(){
cin >> n;
while(n --){
for(int i = 0; i < 5; i ++) cin >> g[i];//读取数据
int res = 10;//用于记录操作的结果
for(int op = 0; op < 32; op ++){//枚举第1行灯的状态 ---- 也可以采用递归实现指数型枚举
int step = 0;//用于记录当前情况的操作步数
memcpy(backup, g, sizeof g);//备份原数组数据 ---- 因为每次枚举都是一种全新的情况
//枚举第一行,若灯灭,则点亮
for(int j = 0; j < 5; j ++){
if(!(op >> j & 1)){//也可以是 if(op >> j & 1) ,因为二者情况数量相同
step ++;
turn(0, j);//翻转当前灯的状况
}
}
//从第一行向下递推至倒数第二行
for(int i = 0; i < 4; i ++){
for(int j = 0; j < 5; j ++){
if(g[i][j] == '0'){//当前行当前位置灯灭
step ++;
turn(i + 1, j);//改变当前行的下一行该列灯的状况,使当前行灯亮
}
}
}
//检验最后一行灯是否全亮,若存在暗灯,则此方案不成立
bool dark = false;
for(int j = 0; j < 5; j ++){
if(g[4][j] == '0'){
dark = true;
break;
}
}
if(!dark) res = min(step, res);
memcpy(g, backup, sizeof backup);//还原数据,用于下次方案的操作
}
if(res > 6) res = -1;
cout << res << endl;
}
return 0;
}
// 另一种解
int _, a[6], ans, aa[6];
string s;
void dj(int x, int y) {
aa[x] ^= (1 << y);
if (x != 1) aa[x - 1] ^= (1 << y);
if (x != 5) aa[x + 1] ^= (1 << y);
if (y != 0) aa[x] ^= (1 << (y - 1));
if (y != 4) aa[x] ^= (1 << (y + 1));
}
void pd(int p) {
int k = 0;
memcpy(aa, a, sizeof(a));
for (int i = 0; i < 5; ++i)
if (!((p >> i) & 1)) {
dj(1, i);
if (++k >= ans) return;
}
for (int x = 1; x < 5; ++x)
for (int y = 0; y < 5; ++y)
if (!((aa[x] >> y) & 1)) {
dj(x + 1, y);
if (++k >= ans) return;
}
if (aa[5] == 31) ans = k;
}
int main() {
ios_base::sync_with_stdio(false), cin.tie(0);
for (cin >> _; _--;) {
memset(a, 0, sizeof(a));
for (int i = 1; i <= 5; ++i) {
cin >> s; // 字符串读入更便利处理
for (int j = 1; j <= 5; ++j) a[i] = a[i] * 2 + (s[j - 1] - '0');
}
ans = 7;
for (int p = 0; p < (1 << 5); p++) pd(p);
cout << (ans == 7 ? -1 : ans) << "\n";
}
return 0;
}
Strange Towers of Hanoi
#define Fi(i, a, b) for (int i = a; i <= b; ++i)
int d[13], f[13];
int main() {
ios_base::sync_with_stdio(false), cin.tie(0);
Fi(i, 1, 12) d[i] = d[i - 1] * 2 + 1;
memset(f, 0x3f, sizeof f), f[1] = 1;
Fi(i, 2, 12) Fi(j, 1, i) f[i] = min(f[i], 2 * f[j] + d[i - j]);
Fi(i, 1, 12) cout << f[i] << "\n";
return 0;
}
Sumdiv (AcWing 97. 约数之和)(数论)(分治)

const int p = 9901;
int pow(int x, int y) {
int ret = 1;
for (; y; y >>= 1) {
if (y & 1) ret = 1ll * ret * x % p;
x = (ll)x * x % p;
}
return ret;
}
int main() {
ios::sync_with_stdio(false), cin.tie(0);
int a, b, ans = 1;
cin >> a >> b;
if (!a) return !puts("0");
for (int i = 2, num; i * i <= a; i++) {
num = 0;
while (a % i == 0) a /= i, num++;
if (num)
ans =
ans * (pow(i, num * b + 1) - 1 + p) % p * pow(i - 1, p - 2) % p;
}
if (a > 1) ans = ans * (pow(a, b + 1) - 1 + p) % p * pow(a - 1, p - 2) % p;
cout << ans << "\n";
return 0;
}
Fractal Streets
题解来源:Click Here
题意:
给你一个原始的分形图,t组数据,对于每组数据,输入3个数n,h,o (n为在第n级,h,o为两个房子的编号),求在第n级情况下,编号为h和o的两个点之间的距离*10为多少。
其中,第n级分形图形成规则如下:
- 首先先在右下角和右上角复制一遍n-1情况下的分形图
- 然后将n-1情况下的分形图顺时针旋转90度,放到左上角
- 最后将n-1情况下的分形图逆时针旋转90度 ,放到左下角
编号是从左上角那个点开始计1,沿着道路计数。

这是著名的通过一定规律无限包含自身的分形图。为了计算方便,我们将题目中房屋编号从0开始编号,那么S与D也都减掉1.
大体思路:设calc(n,m)求编号为m的房屋编号在n级城市中的坐标位置,那么距离是:calc(n,s-1) 与 calc(n,d-1)的距离。
从n(n > 1)级城市由四座n-1级城市组成,其中:
1.左上的n-1级城市由城市结构顺时针旋转90度,从编号的顺序看,该结构还做水平翻转,坐标转换至n级时如下图。
2与3.右上和右下和原始城市结构一样,坐标转换至n级时如下图。

市由城市结构逆时针旋转90度,从编号的顺序看,该结构也做了水平翻转。
旋转坐标的变化可通过公式:

(设len = 2(n-1))当旋转角度是逆时针90度时,也就是顺时针270度时,(x,y)->(y, -x),然后再进行水平翻转,(y,-x)->(-y,-x)。然后再将图形平移到n级图形的左下角,在格子上的坐标变化是,水平方向增加len - 1个位置,垂直方向增加2len - 1个位置。因此坐标(x,y)按照规则转移到了(2len-1-y,len-1-x).
注意:n-1级格子里拥有的房子数量是cnt = 22n /4,即22n-2.
当前编号m在N级格子的哪个方位是:m / cnt.
当前编号m在n-1级格子里的编号是: m %cnt;
详细代码如下:
using ll = long long;
pair<ll, ll> calc(ll n, ll m) {
if (n == 0) return make_pair(0, 0); //边界
ll len = 1ll << (n - 1), cnt = 1ll << (2 * n - 2);
pair<ll, ll> zb = calc(n - 1, m % cnt);
ll x = zb.first, y = zb.second;
ll z = m / cnt;
switch (z) {
case 0: return make_pair(y, x); break;
case 1: return make_pair(x, y + len); break;
case 2: return make_pair(x + len, y + len); break;
case 3: return make_pair(2 * len - y - 1, len - x - 1); break;
}
}
int main() {
int t;
cin >> t;
while (t--) {
ll n, s, d;
cin >> n >> s >> d;
pair<ll, ll> zb;
pair<ll, ll> bz;
double ans = 0;
zb = calc(n, s - 1); //记得-1 QWQ
bz = calc(n, d - 1);
ll x, y;
x = (zb.first - bz.first), y = (zb.second - bz.second); //边长居然是10
ans = sqrt(x * x + y * y) * 10; //喜闻乐见 勾股定理
printf("%.0f\n", ans); //四舍五入
}
return 0;
}
非递归实现组合型枚举
#include <iostream>
#include <vector>
using namespace std;
vector<int> chosen;
int n, m;
void dfs(int x);
int main() {
cin >> n >> m;
dfs(1);
}
void dfs(int x) {
if (chosen.size() > m || chosen.size() + (n - x + 1) < m) return;
if (x == n + 1) {
// if(chosen.size() == 0) return;
for (int i = 0; i < chosen.size(); i++) printf("%d ", chosen[i]);
puts("");
return;
}
chosen.push_back(x);
dfs(x + 1);
chosen.pop_back();
dfs(x + 1);
return;
}
0x02 基本算法-枚举、模拟、递推的更多相关文章
- Berlekamp Massey算法求线性递推式
BM算法求求线性递推式 P5487 线性递推+BM算法 待AC. Poor God Water // 题目来源:ACM-ICPC 2018 焦作赛区网络预赛 题意 God Wate ...
- [数位DP]把枚举变成递推(未完)
动态规划(DP)是个很玄学的东西 数位DP实际上 就是把数字上的枚举变成按位的递推 有伪代码 for i =这一位起始值 i<=这一位终止值 dp[这一位][i]+=dp[这一位-1][i]+- ...
- AtCoder Regular Contest 069 D - Menagerie 枚举起点 模拟递推
arc069.contest.atcoder.jp/tasks/arc069_b 题意:一堆不明身份的动物排成一圈,身份可能是羊或狼,羊一定说实话,狼一定说假话.大家各自报自己的两边是同类还是不同类, ...
- codeforces 676B 模拟 递推
题意:每秒从最高处的杯子倒一杯酒下来,酒流的方式如图,问t秒装满酒的杯子的数目. 思路:把第一杯的值设为t,glass[i][j]=(glass[i-1][j-1]-1)/2+(glass[i-1][ ...
- openjudge1768 最大子矩阵[二维前缀和or递推|DP]
总时间限制: 1000ms 内存限制: 65536kB 描述 已知矩阵的大小定义为矩阵中所有元素的和.给定一个矩阵,你的任务是找到最大的非空(大小至少是1 * 1)子矩阵. 比如,如下4 * 4的 ...
- 【51Nod】1519 拆方块 贪心+递推
[题目]1519 拆方块 [题意]给定n个正整数,\(A_i\)表示第i堆叠了\(A_i\)个石子.每轮操作将至少有一面裸露的石子消除,问几轮所有石子均被消除.\(n \leq 10^5\). [算法 ...
- C. The Fair Nut and String 递推分段形dp
C. The Fair Nut and String 递推分段形dp 题意 给出一个字符串选择一个序列\({p_1,p_2...p_k}\)使得 对于任意一个\(p_i\) , \(s[p_i]==a ...
- [luoguP1011] 车站(递推)
传送门 蒟蒻我关系式没有找出来. 直接模拟递推过程好了. 代码 #include <cstdio> #define N 21 int a, n, m, x, y; int up[N][2] ...
- 0x02 枚举、模拟、递推
1.TYVJ1266(这站是不是已经倒闭了啊) USACO陈年老题,对于这种开关问题啊,最多只按一次,而且第一行随便按完下面的就全确定了,类似的还有固定翻转一个长度的区间,这个也是最多翻一次的而且翻的 ...
- Coconuts, Revisited(递推+枚举+模拟)
Description The short story titled Coconuts, by Ben Ames Williams, appeared in the Saturday Evening ...
随机推荐
- 【matlab混沌理论】1.3.双摆杆基本模型
双摆杆是混沌理论的典型运动模型之一.涉及重力加速度.摆杆长度和质量. 1.双摆杆的摆角分析 input: % 已知物理参数 L1 = 5;L2 = 3; %两摆杆长度和质量 m1 = 3;m2 = 5 ...
- 【UniApp】-uni-app-路由
前言 好,经过上个章节的介绍完毕之后,了解了一下 uni-app-CompositionAPI应用生命周期和页面生命周期 那么了解完了uni-app-CompositionAPI应用生命周期和页面生命 ...
- ubuntu安装cudnn
有些忙,这一段时间,博客就随便写写了--- 默认cuda安装好了,这里就不多说了,我们从cuda的环境变量开始说起: 配置cuda环境变量: 打开终端,输入"gedit ~/.bashrc& ...
- Codeforces #475 div2
题目链接:http://codeforces.com/contest/964 A题 答案n/2+1: B题 讨论三种情况 c>b c==b c<b C题 数论,逆元+快速幂,但是我一直卡在 ...
- 5分钟攻略Spring-Retry框架实现经典重试场景
前言 今天分享干货,控制了篇幅,5分钟内就能看完学会. 主题是Spring-Retry框架的应用,做了一个很清晰的案例,代码可下载自测. 框架介绍 Spring-Retry框架是Spring自带的功能 ...
- bash shell笔记整理——外部命令和内部命令区别
linux命令的类别: 外部命令 内部命令 什么是内部命令 bash shell程序内部自带的命令. 什么是外部命令 不是bash shell内建命令,bash会根据用户给定的命令从PATH环境变量中 ...
- Kernel Memory 入门系列:文档的管理
Kernel Memory 入门系列: 文档的管理 在Quick Start中我们了解到如何快速直接地上传文档.当时实际中,往往会面临更多的问题,例如文档如何更新,如何划定查询范围等等.这里我们将详细 ...
- java判断两个日期是否连续
使用java判断两个日期的天是否连续 import java.text.SimpleDateFormat; import java.util.Date; /** * @author lingkang ...
- Spring 多线程的事务处理
问题起因 Spring 的 JDBC 相关的依赖库已经提供了对 JDBC 类事务处理的统一解决方案,在正常情况下,我们只需要在需要添加事务的业务处理方法上加上 @Transactional 注解即可开 ...
- 揭秘Spring事务失效场景分析与解决方案
在Spring框架中,事务管理是一个核心功能,然而有时候会遇到事务失效的情况,这可能导致数据一致性问题.本文将深入探讨一些Spring事务失效的常见场景,并提供详细的例子以及解决方案. 1. 跨方法调 ...