bzoj4197 [Noi2015]寿司晚宴——状压DP
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4197
首先,两个人选的数都互质可以看作是一个人选了一个数,就相当于选了一个质因数集合,另一个人不能再选;
想把质因数状压起来,但是数量太多;
有个性质是一个数 x 最多有一个大于根号 x 的质因数,把那个拿出来单独考虑的话,剩下的质因数(小于根号500的)只有8个,可以状压;
于是先对2到 n 的每个数处理出单独的质因数和剩下的质因数状态,然后对单独质因数相同的几个数一起进行DP;
单独质因数相同,那么这几个数要么都被第一个人选,要么都被第二个人选,要么不被选;
所以用一个辅助数组 g 承接之前的 f 值,然后分成 g[0] 和 g[1] 分别表示第一个人选还是第二个人选,0和1之间不互相转移;
最后再把 f 赋回来,要注意这整个集合不被选的状态被算了两次,所以再减掉一个原来的值;
感觉自己好难想出来啊,尤其是那个辅助的 g 数组,但想好了却这么简洁。
代码如下:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
int const maxn=,mx=(<<);
int n,p,pri[]={,,,,,,,};
ll f[mx][mx],g[][mx][mx],ans;
struct N{int s,num;}a[maxn];
bool cmp(N x,N y){return x.num<y.num;}
void init()
{
for(int i=;i<=n;i++)
{
int x=i;
for(int j=;j<;j++)
{
if(x%pri[j])continue;
a[i].s|=(<<j);
while(x%pri[j]==)x/=pri[j];
}
a[i].num=x;
}
}
int main()
{
scanf("%lld%lld",&n,&p);
init();
sort(a+,a+n+,cmp);//a+2
f[][]=;
for(int i=;i<=n;i++)
{
if(i==||a[i].num!=a[i-].num||a[i].num==)//1表示没有大于根号n的质因子,所以每次重新DP
memcpy(g[],f,sizeof f),memcpy(g[],f,sizeof f);
for(int j=mx-;j>=;j--)
for(int k=mx-;k>=;k--)//倒序
{
if(j&k)continue;
if(!(a[i].s&k)) (g[][j|a[i].s][k]+=g[][j][k])%=p;
if(!(a[i].s&j)) (g[][j][k|a[i].s]+=g[][j][k])%=p;
}
if(i==n||a[i].num!=a[i+].num||a[i].num==)
{
for(int j=mx-;j>=;j--)
for(int k=mx-;k>=;k--)
// if(!(j&k)) (f[j][k]+=g[0][j][k]+g[1][j][k]-f[j][k])%=p;//已把之前f的值赋给g
if(!(j&k)) (f[j][k]=(g[][j][k]+g[][j][k]-f[j][k])%p+p)%p;//+p%p
}
}
for(int j=mx-;j>=;j--)
for(int k=mx-;k>=;k--)
if(!(j&k)) (ans+=f[j][k])%=p;
printf("%lld\n",ans);
return ;
}
bzoj4197 [Noi2015]寿司晚宴——状压DP的更多相关文章
- 【BZOJ4197】[Noi2015]寿司晚宴 状压DP+分解质因数
[BZOJ4197][Noi2015]寿司晚宴 Description 为了庆祝 NOI 的成功开幕,主办方为大家准备了一场寿司晚宴.小 G 和小 W 作为参加 NOI 的选手,也被邀请参加了寿司晚宴 ...
- 【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种不同的寿 ...
- B4197 [Noi2015]寿司晚宴 状压dp
这个题一开始想到了唯一分解定理,然后状压.但是显然数组开不下,后来想到每个数(n<500)大于19的素因子只可能有一个,所以直接单独存就行了. 然后正常状压dp就很好搞了. 题干: Descri ...
- BZOJ 4197: [Noi2015]寿司晚宴 状压dp+质因数分解
挺神的一道题 ~ 由于两个人选的数字不能有互质的情况,所以说对于一个质因子来说,如果 1 选了,则 2 不能选任何整除该质因子的数. 然后,我们发现对于 1 ~ 500 的数字来说,只可能有一个大于 ...
- [NOI2015]寿司晚宴——状压dp
题目转化:将2~n的数分成两组,可以不选,使得这两组没有公共的质因子.求方案数. 选择了一个数,相当于选择了它的所有质因子. 30分: 发现,n<=30的时候,涉及到的质因子也就10个.2,3, ...
- BZOJ 4197 NOI 2015 寿司晚宴 状压DP
4197: [Noi2015]寿司晚宴 Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 694 Solved: 440[Submit][Status] ...
- NOI 2015 寿司晚宴 (状压DP+分组背包)
题目大意:两个人从2~n中随意取几个数(不取也算作一种方案),被一个人取过的数不能被另一个人再取.两个人合法的取法是,其中一个人取的任何数必须与另一个人取的每一个数都互质,求所有合法的方案数 (数据范 ...
- [NOI2015][bzoj4197] 寿司晚宴 [状压dp+质因数]
题面 传送门 思路 首先,要让两个人选的数字全部互质,那么有一个显然的充要条件:甲选的数字的质因数集合和乙选的数字的质因数集合没有交集 30pt 这种情况下n<=30,也就是说可用的质数只有10 ...
随机推荐
- Angular——内置指令
内置指令 ng-app 指定应用根元素,至少有一个元素指定了此属性. ng-controller 指定控制器 ng-show控制元素是否显示,true显示.false不显示 ng-hide控制元素是否 ...
- JS高级——词法作用域
作用域 1.js中没有块级作用域 2.如果有块级作用域,那么下面代码将会是undefined undefined <script> for (var i = 0; i < 10; i ...
- CSS——float
float:就是在于布局,首先要介绍的是文档流(标准流),之后是浮动布局. 文档流:元素自上而下,自左而右,块元素独占一行,行内元素在一行上显示,碰到父集元素的边框换行. 浮动布局: 1.float: ...
- 【译】x86程序员手册04 - 2.2数据类型
2.2 Data Types 数据类型 Bytes, words, and doublewords are the fundamental data types (refer to Figure 2- ...
- 预处理、const、static、sizeof
1.预处理和宏定义 #define xxxx #ifdef xxxx ; #elseif xxxx; #endif 2.c++求随机数 rand(),rand()会返回一随机数值, 范围在0至RAND ...
- logstash windows下添加服务启动管理
nssm下载链接:http://nssm.cc/release/nssm-2.24.zip
- if判断,while循环,for循环
if判断 if判断其实就是让计算机模拟人的判断 if if 条件: 代码1 代码2 代码3 ... # 代码块(同一缩进级别的代码,例如代码1.代码2和代码3是相同缩进的代码,这三个代码组合在一起就是 ...
- java 异常报错总结
1.java.lang.ArithmeticException:这是算数异常 比如分母位0 2. java.lang.ArrayIndexOutOfBoundsException:数组下标越界异常 3 ...
- 微信小程序支付(JSAPI支付)
开发环境:.NET MVC+ ORM框架(EF) 一.参考文档: 1.微信JSAPI支付官方文档:https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api. ...
- golang bytes 包
类型 []byte 的切片十分常见,Go 语言有一个 bytes 包专门用来解决这种类型的操作方法. bytes 包和字符串包十分类似.而且它还包含一个十分有用的类型 Buffer: import & ...