bzoj2734 集合选数

2023-11-02 11:32
文章标签 集合 bzoj2734 选数

本文主要是介绍bzoj2734 集合选数,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

集合选数

题目背景:

bzoj2734

分析:构造 + 状态压缩DP

表示思路比较清奇啊·····我是没有想到的······我们来考虑如何选择可行的数字,先构造一个矩阵

1   3   9   27   81   243
2   6   18  54   162  486
4   12  36  108  324  972
8   24  72  216  648  1944
16  48  144 432  1296 3888
...

显然我们可以发现这个矩阵中,相邻的数字(上下或者左右)是都不能被选择的,然后每一行做多只会有11个数,那么我们可以选择直接状压每一行然后DP方案数即可,但是我们可以发现,上面这个矩阵中有些数字是没有出现的,出现的为2m3n形式,那么说明我们的矩阵左上角不一定只能为1,还可以为很多其他的数字,例如5,7,稍加分析就可以知道每一次取在之前的矩阵中没有出现过的最小的数字构造新的矩阵就可以了,并且,这样选择的数字,不同的矩阵中不会出现相同的数(质因子不同)所以直接利用乘法原理相乘即可。

Source

/*created by scarlyw
*/
#include <cstdio>
#include <string>
#include <algorithm>
#include <cstring>
#include <iostream>
#include <cmath>
#include <cctype>
#include <vector>
#include <set>
#include <queue>inline char read() {static const int IN_LEN = 1024 * 1024;static char buf[IN_LEN], *s, *t;if (s == t) {t = (s = buf) + fread(buf, 1, IN_LEN, stdin);if (s == t) return -1;}return *s++;
}///*
template<class T>
inline void R(T &x) {static char c;static bool iosig;for (c = read(), iosig = false; !isdigit(c); c = read()) {if (c == -1) return ;if (c == '-') iosig = true;	}for (x = 0; isdigit(c); c = read()) x = ((x << 2) + x << 1) + (c ^ '0');if (iosig) x = -x;
}
//*/const int OUT_LEN = 1024 * 1024;
char obuf[OUT_LEN], *oh = obuf;
inline void write_char(char c) {if (oh == obuf + OUT_LEN) fwrite(obuf, 1, OUT_LEN, stdout), oh = obuf;*oh++ = c;
}template<class T>
inline void W(T x) {static int buf[30], cnt;if (x == 0) write_char('0');else {if (x < 0) write_char('-'), x = -x;for (cnt = 0; x; x /= 10) buf[++cnt] = x % 10 + 48;while (cnt) write_char(buf[cnt--]);}
}inline void flush() {fwrite(obuf, 1, oh - obuf, stdout);
}/*
template<class T>
inline void R(T &x) {static char c;static bool iosig;for (c = getchar(), iosig = false; !isdigit(c); c = getchar())if (c == '-') iosig = true;	for (x = 0; isdigit(c); c = getchar()) x = ((x << 2) + x << 1) + (c ^ '0');if (iosig) x = -x;
}
//*/const int MAXN = 18;
const int mod = 1000000000 + 1;
const int MAXX = 100000 + 10;long long n, ans;
long long matrix[MAXN][MAXN];
long long f[MAXN][1 << MAXN | 1]; 
bool vis[MAXX];inline long long calc(int x) {int r;static int line[MAXN];matrix[1][1] = x, vis[x] = true;for (int i = 1; ; ++i) {if (i != 1) {matrix[i][1] = matrix[i - 1][1] * 2;if (matrix[i][1] > n) {r = i - 1;break ;} else vis[matrix[i][1]] = true;}for (int j = 2; ; ++j) {matrix[i][j] = matrix[i][j - 1] * 3;if (matrix[i][j] > n) {line[i] = j - 1;break ;} else vis[matrix[i][j]] = true;}}line[r + 1] = 0;for (int i = 0; i <= r + 1; ++i)for (int j = 0; j < (1 << line[i]); ++j)f[i][j] = 0;f[0][0] = 1;for (int i = 0; i <= r; ++i)for (int j = 0; j < (1 << line[i]); ++j) {if (f[i][j]) {if (j & (j >> 1)) continue ;for (int k = 0; k < (1 << line[i + 1]); ++k) {if (k & j) continue ;f[i + 1][k] = (f[i + 1][k] + f[i][j]) % mod;}}}return f[r + 1][0];
}int main() {R(n), ans = 1;for (int i = 1; i <= n; ++i) if (!vis[i]) ans = ans * calc(i) % mod;std::cout << ans;return 0;
}

这篇关于bzoj2734 集合选数的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/330327

相关文章

uva 11178 计算集合模板题

题意: 求三角形行三个角三等分点射线交出的内三角形坐标。 代码: #include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstring>#include <cmath>#include <stack>#include <vector>#include <

Java基础回顾系列-第六天-Java集合

Java基础回顾系列-第六天-Java集合 集合概述数组的弊端集合框架的优点Java集合关系图集合框架体系图java.util.Collection接口 List集合java.util.List接口java.util.ArrayListjava.util.LinkedListjava.util.Vector Set集合java.util.Set接口java.util.HashSetjava

【408数据结构】散列 (哈希)知识点集合复习考点题目

苏泽  “弃工从研”的路上很孤独,于是我记下了些许笔记相伴,希望能够帮助到大家    知识点 1. 散列查找 散列查找是一种高效的查找方法,它通过散列函数将关键字映射到数组的一个位置,从而实现快速查找。这种方法的时间复杂度平均为(

java集合的概述

集合就是一个容器,我们可以把多个对象放入的容器中。就像水杯(假设容量可以不断扩大)一样,你可以往水杯中不断地添加水,既然是水杯,你就不能往里添加沙子,也就是说集合中添加的对象必须是同一个类型的(引用类型,而不能是基本类型)。 看到集合的介绍会让我们的想起数组,那么集合和数组有什么区别呢? 首先,数组的大小是固定的,而集合理论上大小是不限的。 其次,数组既可以存储基本数据类型的数据,也可以存储

hutool 集合相关交集、差集

开发过程中会遇到集合之间的对比之类的需求,之前经常会自己写个工具类来实现,目前hutool可以帮助我们解决很多问题,接下来我们就来实践下。 相关jar包 <dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>RELEASE</version><scope>compile</sco

Java8中的Stream,让集合操作酸爽起来

简介 java8也出来好久了,接口默认方法,lambda表达式,函数式接口,Date API等特性还是有必要去了解一下。比如在项目中经常用到集合,遍历集合可以试下lambda表达式,经常还要对集合进行过滤和排序,Stream就派上用场了。用习惯了,不得不说真的很好用。 Stream作为java8的新特性,基于lambda表达式,是对集合对象功能的增强,它专注于对集合对象进行各种高效、便利的聚合

算法练习小技巧之有序集合--套路详细解析带例题(leetcode)

前言:         本文详细讲解Python中的有序集合SortedList和C++中的有序集合multiset的用法,配合leetcode的例题来展示实际的用处。(本人水平不够,还无法讲解有序集合的实现方法,只会用)         觉得有帮助或者写的不错可以点个赞,后面也有几道我找出来的题目可以用这个方法快速解决的         (感觉有点水) 目录 有序集合用法讲解:

Java中集合类Set、List和Map的区别

Java中的集合包括三大类,它们是Set、List和Map,它们都处于java.util包中,Set、List和Map都是接口,它们有各自的实现类。Set的实现类主要有HashSet和TreeSet,List的实现类主要有ArrayList,Map的实现类主要有HashMap和TreeMap。那么它们有什么区别呢? Set中的对象不按特定方式排序,并且没有重复对象。但它的有些实现类能对集合中的对

复杂SQL集合(不断收集中)

1.一道SQL语句面试题,关于group by 表内容: 2005-05-09 胜 2005-05-09 胜 2005-05-09 负 2005-05-09 负 2005-05-10 胜 2005-05-10 负 2005-05-10 负 如果要生成下列结果, 该如何写sql语句?             胜 负 2005-05-09 2 2 2005-05-10 1 2 --------

EL表达式获取List集合长度

有一次在jsp页面我要获取后台的一个list集合的长度,当然你可以在后台保存长度然后在页面获取,这是一种方法,现在我介绍另一种方法: 首先:我们在jsp页面导入jstl标签库<%@ taglib prefix="fn" uri="http://java.sun.com/jsp.jstl/functions"%> 然后在你要获取的地方写上:${fn:length(qunarRemarkList)