洛谷传送门
BZOJ传送门
题目描述
《集合论与图论》这门课程有一道作业题,要求同学们求出 { 1 , 2 , 3 , 4 , 5 } \{1, 2, 3, 4, 5\} {1,2,3,4,5}的所有满足以 下条件的子集:若 x x x 在该子集中,则 2 x 2x 2x 和 3 x 3x 3x 不能在该子集中。
同学们不喜欢这种具有枚举性 质的题目,于是把它变成了以下问题:对于任意一个正整数 n ≤ 100000 n\le 100000 n≤100000,如何求出 { 1 , 2 , . . . , n } \{1, 2,..., n\} {1,2,...,n} 的满足上述约束条件的子集的个数(只需输出对 1 , 000 , 000 , 001 1,000,000,001 1,000,000,001 取模的结果),现在这个问题就 交给你了。
输入输出格式
输入格式:
只有一行,其中有一个正整数 n n n,30%的数据满足 n ≤ 20 n\le 20 n≤20。
输出格式:
仅包含一个正整数,表示 { 1 , 2 , . . . , n } \{1, 2,..., n\} {1,2,...,n}有多少个满足上述约束条件 的子集。
输入输出样例
输入样例#1:
4
输出样例#1:
8
解题分析
一道妙妙的题, 提出所有的质数和 1 1 1, 然后横向每次 × 2 \times 2 ×2, 纵向每次 × 3 \times 3 ×3, 就像下面这样:
1 2 4 8 16...
3 6 12 24 48...
9 18 36 72 144...
......
然后我们可以发现对于一个数, 其右边和下面的数不能出现, 那么就可以预处理出每行有几个数和所有合法状态, 状压 D P DP DP就好了。
代码如下:
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cctype>
#include <algorithm>
#include <cstring>
#define R register
#define IN inline
#define W while
#define gc getchar()
#define MX 100500
#define ll long long
#define MOD 1000000001
int n, tot, crs, ans = 1;
int stat[21], avai[4205], dp[21][4205], hd[21];
bool vis[MX];
IN void add(R int ad, int &tar)
{
tar += ad;
if (tar > MOD) tar -= MOD;
}
int main(void)
{
R int i, j, k, l, pre, res, tim;
scanf("%d", &n); int bd;
for (i = 0, bd = (1 << (int)log2(n) + 1) - 1; i <= bd; ++i)
{
if ((i & (i << 1))) continue;
avai[++tot] = i;
}
for (i = 1; i <= n; ++i)
{
if (vis[i]) continue;
for (j = 1; j <= crs; ++j)//reset
{
for (k = 1; avai[k] <= stat[j] && k <= tot; ++k) dp[j][k] = 0;
stat[j] = 0;
}
crs = res = 0;
for (j = i; j <= n; j = j * 3)
hd[++crs] = j;
for (j = 1; j <= crs; ++j)
{
for (k = hd[j], tim = 1; k <= n; k <<= 1, tim <<= 1)
stat[j] |= tim, vis[k] = true;
}
dp[0][1] = 1;
for (j = 1; j <= crs; ++j)
{
pre = j - 1;
for (k = 1; avai[k] <= stat[j] && k <= tot; ++k)
{
for (l = 1; avai[l] <= stat[pre] && l <= tot; ++l)
{
if (!((avai[k]) & avai[l]))
add(dp[pre][l], dp[j][k]);
}
}
}
for (R int j = 1; avai[j] <= stat[crs] && j <= tot; ++j) add(dp[crs][j], res);
ans = 1ll * ans * res % MOD;
}
printf("%d", ans);
}