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 ...
随机推荐
- 网络中 ping 不通 路由表
不管是在window还是在linux中,我们经常会遇到ping不通的问题. 这里的原因很多,比如不同的网段交换机做了一些限制等,这些问题是我们人工不能解决的. 但是,当你发现各自的网关是可以ping的 ...
- 【技术累积】【点】【java】【29】MapUtils
内容 是Apache组织下的commons-collections包中的工具类 <dependency> <groupId>commons-collections</gr ...
- Memcached 之PHP实现服务器集群一致性hash算法
/** * memcached 一致性hash,分布式算法 * Class MemcacheCluster */ class MemcacheCluster { protected $nodes = ...
- linux调试环境时常用的命令 及 常识
1.查找文件或文件夹 所在的目录 sudo find / -name your_filename 示例: wangju@wangju-HP--G4:~$ sudo find / -name .jenk ...
- Ubuntu 18.04 安装chrome浏览器
参考 https://blog.csdn.net/cyem1/article/details/86297197 一分钟安装教程! 1.将下载源加入到系统的源列表(添加依赖) sudo wget htt ...
- 如何让字体大小<12px
transform:scale( ) -webkit-transform:scale( )
- CAD保存DWG文件,设置保存的文件版本号和密码
主要用到函数说明: MxDrawXCustomFunction::Mx_SaveDwgEx 保存DWG文件,可以设置保存的文件版本号和密码,详细说明如下: 参数 说明 IN CString sFile ...
- react 子组件调用父组件方法
import React from 'react'import '../page1/header.css'import { Table } from 'antd'import Child from ' ...
- Django - 基于orm实现用户增删改查
1.基于orm实现用户新增 user_info.html中,增加代码: views.py中,在原user_info函数中,增加判断代码: 备注:最后一句,可以通过return redirect 实现, ...
- redis数据库学习笔记
redis数据库 工作需要,简单了解一下redis数据库,供后续参考和复习使用. 一.简介 Redis是一个开源(BSD许可),内存存储的数据结构服务器,可用作数据库,高速缓存和消息队列代理.它支持字 ...