题目大意:两个人从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转移也有技巧,常规的自己和自己转移为了避免传递性,要另外开一个数组进行转移。但因为这道题的转移方程都是位与|操作,具有递增性,所以倒序枚举就可以减少一些常数

  1. #include <queue>
  2. #include <cstdio>
  3. #include <cstring>
  4. #include <algorithm>
  5. #define ui unsigned int
  6. #define ll long long
  7. #define il inline
  8. #define N (1<<8)+3
  9. #define inf 0x3f3f3f3f
  10. using namespace std;
  11.  
  12. int n;
  13. ll p;
  14. ll f1[N][N],f2[N][N],dp[N][N];
  15. int pr[]={,,,,,,,};
  16. struct node{
  17. int w,f;
  18. friend bool operator < (const node &a,const node &b){
  19. if(a.w!=b.w) return a.w<b.w;
  20. else return a.f<b.f;
  21. }
  22. }s[N];
  23. void get_son()
  24. {
  25. for(int i=;i<=n;i++)
  26. {
  27. int x=i;
  28. for(int j=;j<;j++)
  29. {
  30. if(x%pr[j]==) x/=pr[j],s[i].f|=(<<j);
  31. while(x%pr[j]==) x/=pr[j];
  32. }s[i].w=x;
  33. }
  34. }
  35.  
  36. int main()
  37. {
  38. scanf("%d%lld",&n,&p);
  39. get_son();
  40. sort(s+,s+n+);
  41. f1[][]=f2[][]=dp[][]=;
  42. int m=(<<)-;
  43. for(int i=;i<=n;i++)
  44. {
  45. for(int s1=m;s1>=;s1--)
  46. for(int s2=m;s2>=;s2--){
  47. if(!((s1|s[i].f)&s2)) f1[s1|s[i].f][s2]=(f1[s1|s[i].f][s2]+f1[s1][s2])%p;
  48. if(!(s1&(s2|s[i].f))) f2[s1][s2|s[i].f]=(f2[s1][s2|s[i].f]+f2[s1][s2])%p;}
  49. if(s[i].w==||s[i+].w!=s[i].w)
  50. for(int s1=m;s1>=;s1--)
  51. for(int s2=m;s2>=;s2--)
  52. f1[s1][s2]=f2[s1][s2]=dp[s1][s2]=(f1[s1][s2]+f2[s1][s2]-dp[s1][s2]+p)%p;
  53. }
  54. ll ans=;
  55. for(int s1=m;s1>=;s1--)
  56. for(int s2=m;s2>=;s2--)
  57. ans+=dp[s1][s2],ans%=p;
  58. printf("%lld\n",ans);
  59. return ;
  60. }

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. tf.truncated_normal和tf.random_normal使用方法的区别

    1.tf.truncated_normal使用方法 tf.truncated_normal(shape, mean=0.0, stddev=1.0, dtype=tf.float32, seed=No ...

  2. 02023_Arrays类的方法练习

    1.定义一个方法,接收一个数组,数组中存储10个学生考试分数,该方法要求返回考试分数最低的后三名考试分数. public static int[] method(double[] arr){ Arra ...

  3. OGG For Bigdata To Kafka同步问题处理

    一.问题报错 -- :: ERROR OGG- Java or JNI exception: oracle.goldengate.util.GGException: Error detected ha ...

  4. eclipse svn -- - --- appears to be part of a subversion 1.7 or greater....解决方法

    安装与svn1.7相兼容的flex Eclipse中的SVN(subclipse) 今天差点被TortoiseSVN1.7和subclipse弄崩溃... 还好最后弄好了,在此把方法写出来,以免其他人 ...

  5. linux下添加自定义脚本到开机自启动的方法

    原文链接:http://www.jb51.net/LINUXjishu/183462.html 我的机器有个coreseek服务,但是没加到开启启动中去,导致机房一旦重启了机器,我的服务便不能使用了. ...

  6. HDOJ 3339 In Action

    最短路+01背包 In Action Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Other ...

  7. android布局中显示隐藏动画

    android 在布局中提供属性,能简单的加入动画效果,例如以下: <LinearLayout ... animateLayoutChanges="true" ... /&g ...

  8. 软件測试、ios中的測试概念以及步骤

    软件測试: 软件測试的目标是应该服务于软件项目的目标,能够通过建议反馈使用更加高效的方法和工具,提升软件开发效率以及软件开发质量.同一时候还能够通过过一些手段,更早.更快.很多其它地发现缺陷.从容减少 ...

  9. QT使用tableWidget显示双排列表 而且选中用红框圈出来

    如需转载请标明出处:http://blog.csdn.net/itas109 整个project下载地址:http://download.csdn.net/detail/itas109/7607735 ...

  10. 在外星人电脑上安装windows10和ubuntu16.04双系统小记

    最近刚刚入手了一台Alienware Aurora R6,买这货的主要目的是为了研究Deep Learning.之所以没有买组装机的原因,主要是担心组装机的不稳定,而实验经费中的设备费也还相对充足,于 ...