题目大意:两个人从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+分组背包)的更多相关文章

  1. BZOJ 4197 NOI 2015 寿司晚宴 状压DP

    4197: [Noi2015]寿司晚宴 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 694  Solved: 440[Submit][Status] ...

  2. NOIP模拟 乘积 - 状压dp + 分组背包

    题目大意: 给出n和k,求从小于等于n的数中取出不超过k个,其乘积是无平方因子数的方案数.无平方因子数:不能被质数的平方整除. 题目分析: 10(枚举\(n\le8\)),40(简单状压\(n\le1 ...

  3. HDU - 6125: Free from square (状压DP+分组背包)

    problem:给定N,K.表示你有数1到N,让你最多选择K个数,问有多少种方案,使得选择的数的乘积无平方因子数.N,K<500: solution:显然可以状压DP做,但是500以内的素数还是 ...

  4. 【BZOJ-4197】寿司晚宴 状压DP

    4197: [Noi2015]寿司晚宴 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 694  Solved: 440[Submit][Status] ...

  5. [NOI2015]寿司晚宴 --- 状压DP

    [NOI2015]寿司晚宴 题目描述 为了庆祝NOI的成功开幕,主办方为大家准备了一场寿司晚宴. 小G和小W作为参加NOI的选手,也被邀请参加了寿司晚宴. 在晚宴上,主办方为大家提供了n−1种不同的寿 ...

  6. 【BZOJ4197】[Noi2015]寿司晚宴 状压DP+分解质因数

    [BZOJ4197][Noi2015]寿司晚宴 Description 为了庆祝 NOI 的成功开幕,主办方为大家准备了一场寿司晚宴.小 G 和小 W 作为参加 NOI 的选手,也被邀请参加了寿司晚宴 ...

  7. B4197 [Noi2015]寿司晚宴 状压dp

    这个题一开始想到了唯一分解定理,然后状压.但是显然数组开不下,后来想到每个数(n<500)大于19的素因子只可能有一个,所以直接单独存就行了. 然后正常状压dp就很好搞了. 题干: Descri ...

  8. [NOI2015]寿司晚宴——状压dp

    题目转化:将2~n的数分成两组,可以不选,使得这两组没有公共的质因子.求方案数. 选择了一个数,相当于选择了它的所有质因子. 30分: 发现,n<=30的时候,涉及到的质因子也就10个.2,3, ...

  9. [NOI2015][bzoj4197] 寿司晚宴 [状压dp+质因数]

    题面 传送门 思路 首先,要让两个人选的数字全部互质,那么有一个显然的充要条件:甲选的数字的质因数集合和乙选的数字的质因数集合没有交集 30pt 这种情况下n<=30,也就是说可用的质数只有10 ...

随机推荐

  1. CF140E New Year Garland (计数问题)

    用$m$种颜色的彩球装点$n$层的圣诞树.圣诞树的第$i$层恰由$a_{i}$个彩球串成一行,且同一层内的相邻彩球颜色不同,同时相邻两层所使用彩球的颜色集合不 同.求有多少种装点方案,答案对$p$取模 ...

  2. 【Tool】Mac环境维护

    1. 安装编译opencv https://blog.csdn.net/lijiang1991/article/details/50756065 /Users/yuhua.cheng/Opt/open ...

  3. django rest-farme-work 的使用(1)

    Django REST框架是一个用于构建Web API的强大且灵活的工具包 您可能想要使用REST框架的一些原因: 可浏览性 身份认证 支持ORM和非ORM的序列化 良好的文档支持 安装初步 pip ...

  4. mybatis 批量导入数据到mysql返回批量Id

    1.首先mybatis版本必需是3.3.1或以上 2.mapper配置文件中 <insert id="insertOrderBatch" parameterType=&quo ...

  5. adb简单使用

    一.基本命令 1.查看目前连接的设备/虚拟器的状态 adb devices

  6. VR开发2015年终总结

    本文章由cartzhang编写,转载请注明出处. 所有权利保留. 文章链接:http://blog.csdn.net/cartzhang/article/details/50617605 作者:car ...

  7. SQL优化的思路及基本原则(mysql)

    SQL优化的思路:  1.优化更需要优化的sql:  2.定位优化对象的性能瓶颈:优化前需了解查询的瓶颈是IO还是CPU,可通过PROFILING很容易定位查询的瓶颈.  3.明确优化目标:  4.从 ...

  8. C语言:一个涉及指针函数返回值与printf乱码、内存堆栈的经典案例

    一个奇怪的C语言问题,涉及到指针.数组.堆栈.以及printf.以下实现: 整数向字符串的转换,返回字符串指针,并在main函数中调用printf显示. #include<stdio.h> ...

  9. hdoj--1276--士兵队列训练问题(数组模拟)

    士兵队列训练问题 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total S ...

  10. lightoj--1245--Harmonic Number (II)(数学推导)

    Harmonic Number (II) Time Limit: 3000MS   Memory Limit: 32768KB   64bit IO Format: %lld & %llu S ...