题目传送门:bzoj2734

  这题一个月前看的时候没什么头绪。现在一看,其实超简单。

  我们对于每个在$ [1,n] $范围内的,没有因数2和3的数$ d $,将它的倍数$ 2^a 3^b d $一起处理。因为每个数$ d $之间没有2和3作为公因数,所以统计时互不影响。

  对于$ d $的倍数$ 2^a 3^b d $,我们可以发现如果把它按因子2的次数为行,因子3的次数为列,把这些数排列在一个矩形中,相当于是在一个阶梯状的棋盘上选择最多的互不相邻的格子。这个可以用状压dp计算。

  其实这题的主要难度在于复杂度的分析,我一个月前也是没算出复杂度然后主观否决了这个方案。

  于是我们现在来分析一下时间复杂度:

    对于数$ d $,将其倍数$ 2^a 3^b $排列成的矩形的规模是$ \log_2(\frac{n}{d}) \times \log_3(\frac{n}{d}) $的,而对于一个$ n \times m $的矩形进行状压dp选择最多的互补相邻的格子的时间复杂度为$ O(2.618^mn) $(因为可以预处理出每一行的所有满足选择的格子互不相邻的有效状态,而有效状态的数量是$ O(1.618^m) $的,所以综合起来复杂度就是$ O(2.618^mn) $)。因此,处理数d时所花费的时间复杂度为$ O(\frac{n}{d} \log(\frac{n}{d})) $。

    因此,总时间复杂度为:$ \sum_{d=1}^{n}\frac{n}{d} \log(\frac{n}{d}) = n \log^2 n $

  代码:

#include<cstdio>
#include<cmath>
#define ll long long
#define mod 1000000001
#define maxn 100010
int vis[maxn],can[][<<],st[];
ll a[][],f[][];
int n;
int work(int x)
{
int w=(int)(log(n/x)/log()+1e-)+,h=(int)(log(n/x)/log()+1e-)+,tot=;
a[][]=x;
for(int i=;i<=w;i++)
a[][i]=a[][i-]*;
for(int i=;i<=h;i++)
for(int j=;j<=w;j++)
a[i][j]=a[i-][j]*;
for(int i=;i<=h;i++)
for(int j=;j<=w;j++)
if(a[i][j]<=n)vis[a[i][j]]=;
for(int i=;i<=h;i++)
for(int j=;j<<<w;j++){
int flag=;
for(int k=;k<w;k++)
if((j&(<<k))&&a[i][k+]>n){
flag=; break;
}
if(flag)can[i][j]=;
else can[i][j]=;
}
for(int i=;i<<<w;i++)
if(!(i&(i<<))&&!(i&(i>>)))st[++tot]=i;
f[][]=;
for(int i=;i<=h;i++)
for(int j=;j<=tot;j++){
f[i][j]=;
for(int k=;k<=tot;k++)
if(can[i][st[j]]&&can[i-][st[k]]&&!(st[j]&st[k])){
f[i][j]+=f[i-][k];
if(f[i][j]>=mod)f[i][j]-=mod;
}
}
int ans=;
for(int i=;i<=tot;i++)
if(can[h][st[i]]){
ans+=f[h][i];
if(ans>=mod)ans-=mod;
}
return ans;
}
int main()
{
scanf("%d",&n);
ll ans=;
for(int i=;i<=n;i++)
if(!vis[i])ans=ans*work(i)%mod;
printf("%lld\n",ans);
}

bzoj2734

【bzoj2734】集合选数(有点思维的状压dp)的更多相关文章

  1. bzoj2734 集合选数

    Description <集合论与图论>这门课程有一道作业题,要求同学们求出{1, 2, 3, 4, 5}的所有满足以 下条件的子集:若 x 在该子集中,则 2x 和 3x 不能在该子集中 ...

  2. 『数 变进制状压dp』

    数 Description 给定正整数n,m,问有多少个正整数满足: (1) 不含前导0: (2) 是m的倍数: (3) 可以通过重排列各个数位得到n. \(n\leq10^{20},m\leq100 ...

  3. 【思维题 状压dp】APC001F - XOR Tree

    可能算是道中规中矩的套路题吧…… Time limit : 2sec / Memory limit : 256MB Problem Statement You are given a tree wit ...

  4. “景驰科技杯”2018年华南理工大学程序设计竞赛 A. 欧洲爆破(思维+期望+状压DP)

    题目链接:https://www.nowcoder.com/acm/contest/94/A 题意:在一个二维平面上有 n 个炸弹,每个炸弹有一个坐标和爆炸半径,引爆它之后在其半径范围内的炸弹也会爆炸 ...

  5. 骨牌摆放方案数n*m(状压DP)

    题意:https://www.nitacm.com/problem_show.php?pid=1378 如题. 思路: 从第一行for到最后一行,枚举每一行的所有状态,进行转移,注意答案是dp[最后一 ...

  6. BZOJ_2734_[HNOI2012]集合选数_构造+状压DP

    BZOJ_2734_[HNOI2012]集合选数_构造+状压DP 题意:<集合论与图论>这门课程有一道作业题,要求同学们求出{1, 2, 3, 4, 5}的所有满足以 下条件的子集:若 x ...

  7. POJ 1684 Corn Fields(状压dp)

    描述 Farmer John has purchased a lush new rectangular pasture composed of M by N (1 ≤ M ≤ 12; 1 ≤ N ≤ ...

  8. BZOJ1087【状压DP】

    题目链接[http://www.lydsy.com/JudgeOnline/problem.php?id=1087] 题意:在N×N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案.国王能攻击 ...

  9. 【BZOJ-2734】集合选数 状压DP (思路题)

    2734: [HNOI2012]集合选数 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1070  Solved: 623[Submit][Statu ...

随机推荐

  1. flask建立数据模型数据类型

    https://blog.csdn.net/happyanger6/article/details/53947162 https://blog.csdn.net/happyanger6/article ...

  2. 并发编程 - 线程 - 1.开启线程的两种方式/2.进程与线程的区别/3.Thread对象的其他属性或方法/4.守护线程

    1.开启线程的两种方式: 进程,线程: 进程只是用来把资源集中到一起(进程只是一个资源单位,或者说资源集合)而线程才是cpu上的执行单位) 1.同一个进程内的多个线程共享该进程内的地址资源 2.创建线 ...

  3. leadecode 2 Add Two Numbers

    package leadcode; /** * 2. Add Two Numbers * Medium * 4067 * 953 * * * You are given two non-empty l ...

  4. PCI 设备详解二

    上篇文章主要从硬件的角度分析了PCI设备的特性以及各种寄存器,那么本节就结合LInux源代码分析下内核中PCI设备的各种数据结构以及相互之间的联系和工作机制 2016-10-09 注:一下代码参考LI ...

  5. CListCtrl控件使用方法总结

    今天第一次用CListCtrl控件,遇到不少问题,查了许多资料,现将用到的一些东西总结如下: 以下未经说明,listctrl默认view 风格为report 相关类及处理函数 MFC:CListCtr ...

  6. oracle中 rownum 与 connect by的结合使用

    原文:http://blog.sina.com.cn/s/blog_a26966d90102wwkb.html oracle中 rownum 与 connect by的结合使用 SELECT ROWN ...

  7. java 多线程 day15 CyclicBarrier 路障

    import java.util.concurrent.CyclicBarrier;import java.util.concurrent.ExecutorService;import java.ut ...

  8. Python学习笔记(一)数据类型

    一.整型和浮点型 Python可以处理任意大小的整数,当然包括负整数,在程序中的表示方法和数学上的写法一模一样 age=10 num=-35 score=98.8 二.布尔类型 布尔值和布尔代数的表示 ...

  9. windows平台tensorboard的配置及使用

    由于官网和其他教程里面都是以Linux为平台演示tensorboard使用的,而在Windows上与Linux上会有一些差别,因此我将学习的过程记录下来与大家分享(基于tensorflow1.2.1版 ...

  10. SDUT中大数实现的题目,持续更新(JAVA实现)

    SDUT2525:A-B (模板题) import java.util.Scanner; import java.math.*; public class Main { public static v ...