NOI 2015 寿司晚宴 (状压DP+分组背包)
题目大意:两个人从2~n中随意取几个数(不取也算作一种方案),被一个人取过的数不能被另一个人再取。两个人合法的取法是,其中一个人取的任何数必须与另一个人取的每一个数都互质,求所有合法的方案数
(数据范围毕竟很小,乍一看也不是啥打表找规律的题)
和我之前做过的一道题很类似hdu 6125,但这道题由于题面看起来很玄学,所以正解更难想
但还是 状压DP+分组背包 的套路
因为500以内的任何一个数,只会有一个大于19的质因子,所以对2 3 5 7 11 13 17 19这8个质数进行状压,然后每个数都质因数分解,把小于等于19的质因子存入状态,剩下的因子分组背包搞搞就行了,注意如果剩下的因子是1要单独算一组,否则会出大事情,比如2和3并不是同一组的,如果再来一个4,和2是同一组的,转移就会出错
具体DP的实现呢,定义是第一个人取了状态为s1的数,第二个人取了状态为s2的数
分组背包要把同一组的东西放到连续的一段序列上
对于这道题而言,如果某个人取了某一组的任何一个,那么这一组的其它物品也只能被这个人取/不取
所以额外定义两个状态f1,f2,含义和dp的意义是一样的,只不过在同一组内是f1和f2这两个状态自己和自己转移,然后把答案贡献给dp,即这一组对整体的贡献,然后把dp重新赋给f1,f2,再进行下一组背包
方程
由于f1,f2为了下一层转移,都被加了一次dp值,所以最后要减掉一个dp
即
而f1,f2转移也有技巧,常规的自己和自己转移为了避免传递性,要另外开一个数组进行转移。但因为这道题的转移方程都是位与|操作,具有递增性,所以倒序枚举就可以减少一些常数
#include <queue>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define ui unsigned int
#define ll long long
#define il inline
#define N (1<<8)+3
#define inf 0x3f3f3f3f
using namespace std; int n;
ll p;
ll f1[N][N],f2[N][N],dp[N][N];
int pr[]={,,,,,,,};
struct node{
int w,f;
friend bool operator < (const node &a,const node &b){
if(a.w!=b.w) return a.w<b.w;
else return a.f<b.f;
}
}s[N];
void get_son()
{
for(int i=;i<=n;i++)
{
int x=i;
for(int j=;j<;j++)
{
if(x%pr[j]==) x/=pr[j],s[i].f|=(<<j);
while(x%pr[j]==) x/=pr[j];
}s[i].w=x;
}
} int main()
{
scanf("%d%lld",&n,&p);
get_son();
sort(s+,s+n+);
f1[][]=f2[][]=dp[][]=;
int m=(<<)-;
for(int i=;i<=n;i++)
{
for(int s1=m;s1>=;s1--)
for(int s2=m;s2>=;s2--){
if(!((s1|s[i].f)&s2)) f1[s1|s[i].f][s2]=(f1[s1|s[i].f][s2]+f1[s1][s2])%p;
if(!(s1&(s2|s[i].f))) f2[s1][s2|s[i].f]=(f2[s1][s2|s[i].f]+f2[s1][s2])%p;}
if(s[i].w==||s[i+].w!=s[i].w)
for(int s1=m;s1>=;s1--)
for(int s2=m;s2>=;s2--)
f1[s1][s2]=f2[s1][s2]=dp[s1][s2]=(f1[s1][s2]+f2[s1][s2]-dp[s1][s2]+p)%p;
}
ll ans=;
for(int s1=m;s1>=;s1--)
for(int s2=m;s2>=;s2--)
ans+=dp[s1][s2],ans%=p;
printf("%lld\n",ans);
return ;
}
NOI 2015 寿司晚宴 (状压DP+分组背包)的更多相关文章
- BZOJ 4197 NOI 2015 寿司晚宴 状压DP
4197: [Noi2015]寿司晚宴 Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 694 Solved: 440[Submit][Status] ...
- NOIP模拟 乘积 - 状压dp + 分组背包
题目大意: 给出n和k,求从小于等于n的数中取出不超过k个,其乘积是无平方因子数的方案数.无平方因子数:不能被质数的平方整除. 题目分析: 10(枚举\(n\le8\)),40(简单状压\(n\le1 ...
- HDU - 6125: Free from square (状压DP+分组背包)
problem:给定N,K.表示你有数1到N,让你最多选择K个数,问有多少种方案,使得选择的数的乘积无平方因子数.N,K<500: solution:显然可以状压DP做,但是500以内的素数还是 ...
- 【BZOJ-4197】寿司晚宴 状压DP
4197: [Noi2015]寿司晚宴 Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 694 Solved: 440[Submit][Status] ...
- [NOI2015]寿司晚宴 --- 状压DP
[NOI2015]寿司晚宴 题目描述 为了庆祝NOI的成功开幕,主办方为大家准备了一场寿司晚宴. 小G和小W作为参加NOI的选手,也被邀请参加了寿司晚宴. 在晚宴上,主办方为大家提供了n−1种不同的寿 ...
- 【BZOJ4197】[Noi2015]寿司晚宴 状压DP+分解质因数
[BZOJ4197][Noi2015]寿司晚宴 Description 为了庆祝 NOI 的成功开幕,主办方为大家准备了一场寿司晚宴.小 G 和小 W 作为参加 NOI 的选手,也被邀请参加了寿司晚宴 ...
- B4197 [Noi2015]寿司晚宴 状压dp
这个题一开始想到了唯一分解定理,然后状压.但是显然数组开不下,后来想到每个数(n<500)大于19的素因子只可能有一个,所以直接单独存就行了. 然后正常状压dp就很好搞了. 题干: Descri ...
- [NOI2015]寿司晚宴——状压dp
题目转化:将2~n的数分成两组,可以不选,使得这两组没有公共的质因子.求方案数. 选择了一个数,相当于选择了它的所有质因子. 30分: 发现,n<=30的时候,涉及到的质因子也就10个.2,3, ...
- [NOI2015][bzoj4197] 寿司晚宴 [状压dp+质因数]
题面 传送门 思路 首先,要让两个人选的数字全部互质,那么有一个显然的充要条件:甲选的数字的质因数集合和乙选的数字的质因数集合没有交集 30pt 这种情况下n<=30,也就是说可用的质数只有10 ...
随机推荐
- 利用vue-gird-layout 制作可定制桌面 (二)
添加资源池 根据项目需求 添加, 实例两个数据 { "mainData": [ { "x": 0, "y": 0, "w" ...
- weex手机端安全键盘
github地址:weexSafeKeyboard 效果图: 技术依赖:框架:weex+vue 弹出层:weex-ui 图标:iconfont 说明:1.如果不想用到weex-ui,可以把inputk ...
- vue-cli快速搭建
vue-cli是用于开发大型vue项目的脚手架工具,使用vue-cli搭建好平台后,只需要关注程序的开发,不用过多的花时间去思考文件配置的问题 当然,还是可以任意进行自定义配置,官方地址:vue-cl ...
- struct 模块解决 TCP黏包问题
首先来看一下产生黏包现象的一段代码: # server.py 服务端 import socket sk = socket.socket() sk.bind(('127.0.0.1',9000)) ...
- 使用Spring Initializer快速创建Spring Boot项目
目录结构 IDE都支持使用Spring的项目创建向导快速创建一个Spring Boot项目:选择我们需要的模块:向导会联网创建Spring Boot项目:默认生成的Spring Boot项目: 主程序 ...
- windows无法开机解决方法
电脑启动弹出错误Ntldr is missing , 解决方法:重新从xp中拷贝一个出来粘贴上就行 电脑启动弹出错误Ntldr is compressed ,表示分区中的文件被压缩了 解决方法:首先把 ...
- git常规使用的命令
注: xxxx代表你的分支名称 1:本地新建一个分支,与远程分支关联: git branch --set-upstream-to origin/xxxx xxxx 2:创建本地分支: git ...
- HDU 5171
这道题本来很水,以前做过一样的,斐波那契数列,用矩阵快速幂的方法求,本来很水,以前做过很多次,为毛做的时候没想到T_T #include <iostream> #include <c ...
- [Tailwind] Style Elements on hover and focus with Tailwind’s State Variants
In this lesson, we learn how to target specific states of elements and apply styles only when those ...
- Visual C++ 经常使用快捷键
大写和小写 Ctrl+Shift+U: 所有变为大写 Ctrl+U: 所有变为小写 凝视 Ctrl+K+Crtr+C: 凝视选定内容 Ctrl+K+Crtr+U: 取消选定凝视内容 折叠 折叠代码: ...