ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

题解 [HNOI2012]集合选数

2020-10-22 15:02:27  阅读:223  来源: 互联网

标签:... Int 题解 void HNOI2012 int read template 选数


题目传送门

题目大意

直接看题面吧。

思路

感觉挺水的一道题啊?怎么评到紫色的啊?考试的时候LJS出了这个题的加强版我就只想出这个思路,然后就爆了。。。

不难发现,我们可以构造矩阵:

x 2x 4x 6x ... 
3x 6x 12x 24x 48x ...
9x 18x 36x ...

然后实际上就相当于在这个矩阵中选出一些数使得两两不相邻。因为行数列数都是 \(\log\) 级别的,所以直接状压就好了。

\(\texttt{Code}\)

#include <bits/stdc++.h>
using namespace std;

#define Int register int
#define mod 1000000001
#define MAXN 1000005

template <typename T> void read (T &x){char c = getchar ();x = 0;int f = 1;while (c < '0' || c > '9') f = (c == '-' ? -1 : 1),c = getchar ();while (c >= '0' && c <= '9') x = x * 10 + c - '0',c = getchar ();x *= f;}
template <typename T,typename ... Args> void read (T &x,Args& ... args){read (x),read (args...);}
template <typename T> void write (T x){if (x < 0) x = -x,putchar ('-');if (x > 9) write (x / 10);putchar (x % 10 + '0');}
template <typename T> void Mx (T &a,T b){a = max (a,b);}
template <typename T> void Mi (T &a,T b){a = min (a,b);}

bool mark[MAXN];
int n,a[25][25],lim[25];

void init (int x){
	a[1][1] = x;
	for (Int i = 1;i <= 15;++ i){
		if (i > 1) a[i][1] = a[i - 1][1] * 3;
		if (a[i][1] > n) break;
		for (Int j = 2;j <= 20;++ j){
			a[i][j] = a[i][j - 1] * 2;
			if (a[i][j] > n){
				lim[i] = j - 1;
				break;
			}
		}
		for (Int j = 1;j <= lim[i];++ j) mark[a[i][j]] = 1;
	}
} 

bool chk[1 << 21];
int dp[2][1 << 22];

int WorkDP (){
	int endl = 0;
	for (Int i = 0;i < (1 << lim[1]);++ i) dp[1][i] = chk[i];
	for (Int i = 2;i <= 15;++ i){
		if (a[i][1] > n){
			endl = i - 1;
			break;
		}
		for (Int S = 0;S < (1 << lim[i]);++ S) if (chk[S]){
			dp[i & 1][S] = 0;
			for (Int S1 = 0;S1 < (1 << lim[i - 1]);++ S1)
				if ((S & S1) == 0) dp[i & 1][S] += dp[i - 1 & 1][S1],dp[i & 1][S] %= mod;
		}
		else dp[i & 1][S] = 0;
	}
	int ans = 0;
	for (Int S = 0;S < (1 << lim[endl]);++ S) ans += dp[endl & 1][S],ans %= mod;
	return ans;
}

signed main(){
	read (n);int res = 1;
	for (Int i = 0;i < (1 << 20);++ i) chk[i] = ((i & (i >> 1)) == 0);
	for (Int i = 1;i <= n;++ i) if (!mark[i]) init (i),res = 1ll * res * WorkDP () % mod;
	write (res),putchar ('\n');
	return 0;
}

标签:...,Int,题解,void,HNOI2012,int,read,template,选数
来源: https://www.cnblogs.com/Dark-Romance/p/13858307.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有