题目链接

BZOJ4197

题解

两个人选的数都互质,意味着两个人选择了没有交集的质因子集合

容易想到将两个人所选的质因子集合作为状态\(dp\)

\(n\)以内质数很多,但容易发现\(\sqrt{n} \approx 22.3\),这里边的质数只有\(8\)个,而大于\(\sqrt{n}\)的质因子只会出现一次,可以特殊讨论

我们先将所有数按最大质因子排序,如果最大质因子在那\(8\)个质数里边,就记为\(1\)

我们设\(f[i][s1][s2]\)表示选了前\(i\)个数,两人的质因子集合分别为\(s1\)和\(s2\)的方案数

那么显然

\[ans = \sum\limits_{s1 \cap s2 = \emptyset} f[n][s1][s2]
\]

对于最大质因子不超过\(sqrt{n}\)的那些数,我们可以枚举加入\(s1\)或\(s2\)进行转移

对于同一组最大质因数为\(x\)的数,我们先将\(f\)拷贝到\(g\)中,令\(g[0|1][i][s1][s2]\)表示该最大质因数加入谁中,选了前\(i\)个数,质因子集合为\(s1\),\(s2\)的方案数

求完后令\(f[i][s1][s2] = g[0][i][s1][s2] + g[1][i][s1][s2] - f[i][s1][s2]\),因为原来的\(f\)是不包含这一组数的方案,而两个\(g\)都包含了不包含这一组数的方案数,要减去一个

由于空间问题,\(f\)和\(g\)都要通过逆序转移压掉\(i\)那一维

然后就做完了

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<map>
#define Redge(u) for (int k = h[u],to; k; k = ed[k].nxt)
#define REP(i,n) for (int i = 1; i <= (n); i++)
#define mp(a,b) make_pair<int,int>(a,b)
#define cls(s) memset(s,0,sizeof(s))
#define cp pair<int,int>
#define LL long long int
using namespace std;
const int maxn = 505,maxm = 1 << 8,INF = 1000000000;
inline int read(){
int out = 0,flag = 1; char c = getchar();
while (c < 48 || c > 57){if (c == '-') flag = -1; c = getchar();}
while (c >= 48 && c <= 57){out = (out << 3) + (out << 1) + c - 48; c = getchar();}
return out * flag;
}
int f[maxm][maxm],g[2][maxm][maxm];
int n,P,a[maxn];
int p[] = {2,3,5,7,11,13,17,19};
struct node{
int x,p;
}e[maxn];
inline bool operator <(const node& a,const node& b){
return a.p < b.p;
}
int getp(int x){
for (int i = 0; i < 8; i++)
if (x % p[i] == 0) while (x % p[i] == 0) x /= p[i];
return x;
}
void init(){
for (int i = 2; i <= n; i++)
for (int k = 0; k < 8; k++)
if (i % p[k] == 0)
a[i] |= (1 << k);
}
int main(){
n = read(); P = read(); init();
for (int i = 2; i <= n; i++) e[i].x = i,e[i].p = getp(i);
sort(e + 2,e + 1 + n);
f[0][0] = 1;
for (int i = 2; i <= n; i++){
int x = e[i].x,s = a[x];
if (e[i].p == 1){
for (int j = maxm - 1; ~j; j--){
for (int k = maxm - 1; ~k; k--){
int t = f[j][k];
f[j][k | s] = (f[j][k | s] + t) % P;
f[j | s][k] = (f[j | s][k] + t) % P;
}
}
}
else {
for (int j = 0; j < maxm; j++)
for (int k = 0; k < maxm; k++)
g[0][j][k] = g[1][j][k] = f[j][k];
int nxt = i;
while (nxt < n && e[nxt + 1].p == e[i].p) nxt++;
for (int l = 0; l <= nxt - i; l++){
x = e[l + i].x,s = a[x];
for (int j = maxm - 1; ~j; j--){
for (int k = maxm - 1; ~k; k--){
g[0][j | s][k] = (g[0][j | s][k] + g[0][j][k]) % P;
g[1][j][k | s] = (g[1][j][k | s] + g[1][j][k]) % P;
}
}
}
i = nxt;
for (int j = 0; j < maxm; j++)
for (int k = 0; k < maxm; k++)
f[j][k] = (((g[1][j][k] + g[0][j][k]) % P - f[j][k]) % P + P) % P;
}
}
int ans = 0;
for (int j = 0; j < maxm; j++)
for (int k = 0; k < maxm; k++)
if (!(j & k)) ans = (ans + f[j][k]) % P;
printf("%d\n",ans);
return 0;
}

BZOJ4197 [Noi2015]寿司晚宴 【状压dp】的更多相关文章

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

随机推荐

  1. equals和==方法比较(一)

    问题描述 今天在使用spotbugs代码走查时发现这样一个问题,两个Long类型的变量使用==判断数值是否相等,spotbugs提示这是一个很致命的错误,代码大概如下, Long l1=123l; L ...

  2. (原创)python发送邮件

    这段时间一直在学习flask框架,看到flask扩展中有一个mail插件,所以今天就给大家演示如果发邮件. 首先我注册了一个163邮箱,需要开启smtp功能,因为咱们python发送邮件经过的是smt ...

  3. Tp框架之命名空间

    命名空间,相当于虚拟目录 实现自动加载类的机制 初始命名空间:Library文件夹 初始命名空间下面有很多根命名空间: 1.Library里面的文件夹 2.APP的模块文件夹 在tp框架中,只有这两个 ...

  4. Linux TCP/IP调优参数 /proc/sys/net/目录

    所有的TCP/IP调优参数都位于/proc/sys/net/目录. 例如, 下面是最重要的一些调优参数,后面是它们的含义: /proc/sys/net/core/rmem_default " ...

  5. Selenium2+python自动化-xpath定位语法

    前言    在上一篇简单的介绍了用工具查看目标元素的xpath地址,工具查看比较死板,不够灵活,有时候直接复制粘贴会定位不到.这个时候就需要自己手动的去写xpath了,这一篇详细讲解xpath的一些语 ...

  6. python yagmail第三方库发送邮件--更简洁

    1.安装第三方库yagmail: pip install yagmail 2.上代码 import yagmail import os def send_email(): #链接邮箱服务器 serve ...

  7. Linux工作管理

    工作管理? 其实也就是把程序放到后台来管理,在windows中也就是最小化,在Linux中是通过命令把程序放到后台中.jobs命令查看后台程序. 对于第一点注意事项,mysql启动是例外的,要是叉掉了 ...

  8. application/x-www-urlencoded与multipart/form-data

    学习ajax时,学到了GET与POST两种HTTP方法,于是去W3C看了二者的区别,里面提到了二者的编码类型不同,就在网上查阅了相关资料, 在这里把我查阅到的相关结果记录在此,方便以后学习,详细了解一 ...

  9. 深圳第XX天

    今天早晨,面了一家小公司.先说结果吧,面过了.但是,总感觉太假了.面试中很多问题都没有回答上来.然后老板看了一下简历,问:期薪资多少?我想了想,说7000.啊,要不留下来看看?我答应了.不到十分钟,就 ...

  10. PRML学习笔记第一章

    [转] PRML笔记 - 1.1介绍 模式识别的目标 自动从数据中发现潜在规律,以利用这些规律做后续操作,如数据分类等. 模型选择和参数调节 类似的一族规律通常可以以一种模型的形式为表达,选择合适模型 ...