bzoj2734 [HNOI2012]集合选数(状压DP)
2017-12-17 12:38
357 查看
bzoj2734 [HNOI2012]集合选数
原题地址:http://www.lydsy.com/JudgeOnline/problem.php?id=2734题意:
对于任意一个正整数 n,如何求出{1, 2,…, n} 的满足:
“若 x 在该子集中,则 2x 和 3x 不能在该子集中”的子集的个数(只需输出对 1,000,000,001 取模的结果)。
数据范围
n≤100000
题解:
神题。
首先,它的约束条件不是2x,3x,4x…而只是2x,3x。
为什么只有两个且偏偏是互质的两个数呢?
因为它可以充当两个base来构造一个矩形:
x2x4x8x16x⋮3x6x12x24x⋯9x18x36x⋱27x⋮⋯
那么这个矩形的相邻两个数不能同时选。
注意到矩形最多只有18行11列,那么就转化成了一个很经典的状压DP了。
当然一个矩形没有包含完所有的数,取下一个没有包含的数再构造矩形,以此类推…矩形规模不断减小。
各个矩形的答案相乘就是最终答案。
代码:
#include<cstdio> #include<iostream> #include<cstring> #include<algorithm> #define LL long long using namespace std; const int mod=1000000001; const int M=(1<<18)+5; const int N=100005; int n,ans=0,ok[M],R,C; int f[20][20],dp[20][M],lim[20],po[20]; bool vis ; inline int getans(int x) { memset(lim,0,sizeof(lim)); f[1][1]=x; R=1;C=1; vis[x]=1; while(f[1][C]*3<=n) {f[1][C+1]=f[1][C]*3; C++; vis[f[1][C]]=1;} while(f[R][1]*2<=n) {f[R+1][1]=f[R][1]*2; R++; vis[f[R][1]]=1;} lim[1]=C; for(int i=2;i<=R;i++) for(int j=2;j<=C;j++) { f[i][j]=f[i][j-1]*3; if(f[i][j]>n){f[i][j]=n+1; break;} vis[f[i][j]]=1; lim[i]=j; } for(int i=1;i<=R;i++) if(!lim[i]) lim[i]=1; int top=(1<<lim[1]); for(int i=0;i<top;i++) if(ok[i]) dp[1][i]=1; else dp[1][i]=0; for(int i=2;i<=R;i++) { int lt=top; top=(1<<lim[i]); for(int j=0;j<=top;j++) dp[i][j]=0; for(int s=0;s<lt;s++) if(dp[i-1][s]) { for(int t=0;t<top;t++) { if(ok[t]&&((t&s)==0)) dp[i][t]=(dp[i][t]+dp[i-1][s])%mod; } } } int ans=0; for(int i=0;i<top;i++) ans=(ans+dp[R][i])%mod; return ans; } int main() { scanf("%d",&n); for(int i=0;i<M;i++) if(i&(i<<1)) ok[i]=0; else ok[i]=1; for(int i=0;i<=18;i++) po[i]=1<<i; int ret=1; for(int i=1;i<=n;i++) { if(!vis[i]) { int ans=getans(i); ret=(1LL*ret*ans)%mod; } } printf("%d\n",ret); return 0; }
相关文章推荐
- bzoj 2734: [HNOI2012]集合选数 状压dp
- BZOJ 2734: [HNOI2012]集合选数 [DP 状压 转化]
- bzoj2734:[HNOI2012]集合选数(状压DP)
- BZOJ2734 HNOI2012集合选数(状压dp)
- [BZOJ2734][HNOI2012]集合选数(状压DP)
- [BZOJ2734][HNOI2012]集合选数-状压DP
- BZOJ 2734: [HNOI2012]集合选数( 状压dp )
- bzoj 2734: 2734: [HNOI2012]集合选数 (状压DP)
- BZOJ 2734 [HNOI2012]集合选数 状压+思路
- 2734: [HNOI2012]集合选数 (状压dp)
- bzoj2734: [HNOI2012]集合选数 压状dp
- 【BZOJ 2734】[HNOI2012]集合选数 状压dp
- 【bzoj2734】【HNOI2012】【状压DP】集合选数
- BZOJ_2734_[HNOI2012]集合选数_构造+状压DP
- [ DP ] [ HNOI2012 ] BZOJ2734
- bzoj2734 [HNOI2012]集合选数
- 【bzoj2734】[HNOI2012]集合选数
- BZOJ 2734: [HNOI2012]集合选数 乱搞DP
- bzoj 2734: [HNOI2012]集合选数 状压DP
- bzoj2734【HNOI2012】集合选数