[HNOI2012]集合选数
[HNOI2012]集合选数
题目描述
《集合论与图论》这门课程有一道作业题,要求同学们求出
同学们不喜欢这种具有枚举性质的题目,于是把它变成了以下问题:对于任意一个正整数
对于
对于
思路点拨
我看到其余的题解都是从构造的角度讲的,但实际上,这个角度并不好出解。我们可以从图论的角度更加容易地思考这个问题。
我们这么思考,对于一个元素
首先,这个图是一个个独立的联通块,这些连通块我们可以分开计数。每一个连通块都是以某一个不含
但是只有这样,不足以出解。另一个性质就是,这些图是一个个残缺不全的网格图。因为,对于一个
#include<bits/stdc++.h>
#define int long long
using namespace std;
inline int read(){
int x=0,f=1;
char ch=getchar();
while(ch<'0'||ch>'9'){
if(ch=='-') f=-f;
ch=getchar();
}
while(ch>='0'&&ch<='9'){
x=x*10+ch-'0';
ch=getchar();
}
return x*f;
}
const int MAXN=12,mod=1e9+1;
int n,f[20][1<<MAXN];
int a[20];
int qpow(int a,int b){
int ans=1,base=a;
while(b){
if(b&1) ans=ans*base;
base=base*base;
b>>=1;
}
return ans;
}
int p[1<<MAXN],tot;
bool check(int x){
if(x&(x<<1)) return 0;
if(x&(x>>1)) return 0;
return 1;
}
signed main(){
n=read();
int ans=1;
for(int i=1;i<=n;i++){
if(i%2==0||i%3==0) continue;
memset(a,0,sizeof(a));
int x,y;
for(x=1;i*qpow(3,x-1)<=n;x++);
for(y=1;i*qpow(2,y-1)<=n;y++);
x--,y--;
for(int j=1;j<=y;j++)
for(int k=1;k<=x;k++)
if(i*qpow(3,k-1)*qpow(2,j-1)>n)
a[j]+=(1<<(k-1));
int cnt=0;
memset(f,0,sizeof(f));
tot=0;
for(int i=0;i<(1<<x);i++)
if(check(i)) p[++tot]=i;
for(int j=1;j<=tot;j++)
if(!(a[1]&p[j]))f[1][j]=1;
for(int j=2;j<=y;j++){
for(int k=1;k<=tot;k++)
if(!(a[j]&p[k]))
for(int l=1;l<=tot;l++)
if(!(p[k]&p[l]))
f[j][k]=(f[j][k]+f[j-1][l])%mod;
}
for(int j=1;j<=tot;j++)
cnt+=f[y][j];
ans=ans*cnt%mod;
}
cout<<ans;
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(1)