【BZOJ4197】[Noi2015]寿司晚宴

Description

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

在晚宴上,主办方为大家提供了 n−1 种不同的寿司,编号 1,2,3,…,n−1,其中第 i 种寿司的美味度为 i+1 (即寿司的美味度为从 2 到 n)。
现在小 G 和小 W 希望每人选一些寿司种类来品尝,他们规定一种品尝方案为不和谐的当且仅当:小 G 品尝的寿司种类中存在一种美味度为 x 的寿司,小 W 品尝的寿司中存在一种美味度为 y 的寿司,而 x 与 y 不互质。
现在小 G 和小 W 希望统计一共有多少种和谐的品尝寿司的方案(对给定的正整数 p 取模)。注意一个人可以不吃任何寿司。

Input

输入文件的第 1 行包含 2 个正整数 n,p,中间用单个空格隔开,表示共有 n 种寿司,最终和谐的方案数要对 p 取模。

Output

输出一行包含 1 个整数,表示所求的方案模 p 的结果。

Sample Input

3 10000

Sample Output

9

HINT

2≤n≤500

0<p≤1000000000

题解:我们考虑每个素数,它要么在A中,要么在B中,要么都不在。我们定义<sqrt(500)(更具体的说是<=19,因为23*29>500)的质数为小质数,其余的为大质数,则2-n中的任意一个数都可以表示成1(或0)个大质数*若干个小质数。因此我们可以状压小质数,枚举大质数。

用g[0或1][x][y]表示当前的大质数在A或B中,A的小质数状态为x,B的小质数状态为y的方案数。我们预处理出对于每个大质数,可以和它搭配的 小质数组 有哪些(其实就是枚举一个大质数p的所有倍数,将所有倍数都分解质因数)。如果当前这个数要被A选,相当于A既要选这个大质数也要选这个 小质数组 ,并且B既不能选这个大质数也不能选这个 小质数组 中的任一个质数。我们设这个 小质数组 的状态为S,得到DP方程:

g[0][x|S][y]=g[0][x|S][y]+g[0][x][y]
g[1][x][y|S]=g[1][x][y|S]+g[1][x][y]

我们用f[x][y]统计答案,但是发现存在重复的情况。你可以理解为虽然这个数被A抢走了,使得B不能选这个数,但是A也不想选这个数。或者这个数被B抢走了,但是B也不想选。那么重复的方案数是多少呢?就是之前的f[x][y]。所以新的f[x][y]=g[0][x][y]+g[1][x][y]-旧的f[x][y]。

同时,对于不包含大质数的数,要特殊处理。对于不同的大质数,用乘法原则统计答案(因为A可以把好多大质数都抢走);对于不同的小质数选择方法,用加法原则统计答案(小质数不能既给A又给B);DP的时候要时刻满足x&y==0。(以上都是只有本蒟蒻才不明白的地方。)

#include <cstdio>
#include <cstring>
#include <iostream>
#include <vector>
using namespace std;
int n,mod,ans;
int f[1<<8][1<<8],g[2][1<<8][1<<8];
int p2[510];
int pri[]={2,3,5,7,11,13,17,19};
vector<int> v[510];
int getpri(int x)
{
int i,ret=0;
for(i=0;i<8;i++)
{
if(x%pri[i]==0)
{
ret|=(1<<i);
while(x%pri[i]==0) x/=pri[i];
}
}
v[x].push_back(ret);
}
int main()
{
scanf("%d%d",&n,&mod);
int i,j,x,y;
for(i=2;i<=n;i++) getpri(i);
f[0][0]=1;
for(j=0;j<v[1].size();j++)
{
for(x=(1<<8)-1;~x;x--)
{
for(y=(1<<8)-1;~y;y--) if(!(x&y))
{
if(!(y&v[1][j])) f[x|v[1][j]][y]=(f[x|v[1][j]][y]+f[x][y])%mod;
if(!(x&v[1][j])) f[x][y|v[1][j]]=(f[x][y|v[1][j]]+f[x][y])%mod;
}
}
}
for(i=23;i<=n;i++)
{
if(!v[i].size()) continue;
for(x=0;x<(1<<8);x++) for(y=0;y<(1<<8);y++) if(!(x&y)) g[0][x][y]=g[1][x][y]=f[x][y];
for(j=0;j<v[i].size();j++)
{
for(x=(1<<8)-1;~x;x--)
{
for(y=(1<<8)-1;~y;y--) if(!(x&y))
{
if(!(y&v[i][j])) g[0][x|v[i][j]][y]=(g[0][x|v[i][j]][y]+g[0][x][y])%mod;
if(!(x&v[i][j])) g[1][x][y|v[i][j]]=(g[1][x][y|v[i][j]]+g[1][x][y])%mod;
}
}
}
for(x=0;x<(1<<8);x++) for(y=0;y<(1<<8);y++) f[x][y]=((g[0][x][y]+g[1][x][y]-f[x][y])%mod+mod)%mod;
}
for(x=0;x<(1<<8);x++) for(y=0;y<(1<<8);y++) ans=(ans+f[x][y])%mod;
printf("%d",ans);
return 0;
}

【BZOJ4197】[Noi2015]寿司晚宴 状压DP+分解质因数的更多相关文章

  1. bzoj4197 [Noi2015]寿司晚宴——状压DP

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4197 首先,两个人选的数都互质可以看作是一个人选了一个数,就相当于选了一个质因数集合,另一个 ...

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

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

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

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

  4. BZOJ 4197: [Noi2015]寿司晚宴 状压dp+质因数分解

    挺神的一道题 ~ 由于两个人选的数字不能有互质的情况,所以说对于一个质因子来说,如果 1 选了,则 2 不能选任何整除该质因子的数. 然后,我们发现对于 1 ~ 500 的数字来说,只可能有一个大于 ...

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

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

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

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

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

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

  8. NOI 2015 寿司晚宴 (状压DP+分组背包)

    题目大意:两个人从2~n中随意取几个数(不取也算作一种方案),被一个人取过的数不能被另一个人再取.两个人合法的取法是,其中一个人取的任何数必须与另一个人取的每一个数都互质,求所有合法的方案数 (数据范 ...

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

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

随机推荐

  1. 【转载】51CTO-Android设置模拟器屏幕大小

    在Eclipse Android中设置模拟器屏幕大小是本文要介绍的内容,主要是来了解并学习Eclipse Android中模拟器的设置,具体关于Eclipse Android内容的详解来看本文.   ...

  2. Linux和Cisco命令行通用快捷键。

    Ctrl a e 行首,行尾(ahead,end)Esc f b 单词首,单词尾Ctrl f b 移动光标(forward,backwards) Ctrl u k 剪切光标前所有,剪切光标后所有Ctr ...

  3. 洛谷 P2863 [USACO06JAN]牛的舞会The Cow Prom-强连通分量(Tarjan)

    本来分好组之后,就确定好了每个人要学什么,我去学数据结构啊. 因为前一段时间遇到一道题是用Lca写的,不会,就去学. 然后发现Lca分为在线算法和离线算法,在线算法有含RMQ的ST算法,前面的博客也写 ...

  4. 你值得关注的几种常见的js设计模式

    前言 潜水了一段时间,今天空闲时间复盘下之前的知识点,聊聊 js 几种常见的设计模式. 掌握 JavaScript 中常见的一些设计模式,对我们书写规范性代码,可维护性代码有很大的帮助. ps:最近在 ...

  5. ArcGIS 开发时,解决__类型“XX”同时存在于“”和“”中__的错误

    错误提示:类型“ESRI.ArcGIS.ADF.BaseClasses.BaseCommand”同时存在于“e:\Program Files\ArcGIS\DeveloperKit10.2\DotNe ...

  6. HTTP 代理(转)

    什么是代理服务器 Web代理(proxy)服务器是网络的中间实体. 代理位于Web客户端和Web服务器之间,扮演“中间人”的角色. HTTP的代理服务器即是Web服务器又是Web客户端. Fiddle ...

  7. ios6.0 siri语音识别

    Siri 让你能够利用语音来完成发送信息.安排会议.拨打电话等更多事务* .只需像平常一样讲话,就能让 Siri 帮你做事.你会发现 Siri 是如此易用而且能干,精彩用法越用你会发现越多. 懂你所说 ...

  8. 关于Android TaskAffinity的那些事儿

    正常情况下,如果应用已经启动,并将应用切到后台,在通知栏中调起页面时,该应用的Task首先会被调起,然后会将我们的Activity显示在这个Task的顶端.手机百度的通知栏里面有一个快速搜索栏,无论什 ...

  9. Linux进程的睡眠和唤醒

    1   Linux进程的睡眠和唤醒 在Linux中,仅等待CPU时间的进程称为就绪进程,它们被放置在一个运行队列中,一个就绪进程的状态标志位为TASK_RUNNING.一旦一个运行中的进程时间片用完, ...

  10. 2017.2.20 activiti实战--第二章--搭建Activiti开发环境及简单示例(二)简单示例

    学习资料:<Activiti实战> 第一章 搭建Activiti开发环境及简单示例 2.5 简单流程图及其执行过程 (1)leave.bpmn 后缀名必须是bpmn.安装了activiti ...