P2150 [NOI2015] 寿司晚宴

刚开始看错题了,推了一个与原题类似的 DP 方程,然后不会优化,笑了。

思路

首先看到 \(n\) 很小,然后质因子个数就更少了。

因此第一反应是将所有的质因子状压进一个状态里,然后互相判断有没有互质即可。

但是 500 以内的质因子个数并不少,有接近 100 个,因此这只是 30 分的暴力。

但是有一个比较常见的优化:每个数只会有一个大于 \(\sqrt n\) 的质因子。因此我们将这种因子称为“大质因子”。

我们预处理出每个数的大质因子是多少,将所有大质因子相同的数一起转移。

与暴力类似的,我们设 \(f1_{s1,s2},f2_{s1,s2}\) 分别表示所有大质因子相同的数只能第一个人选或不选的方案数,只能第二个人选或不选的方案数。(因为两个人不能同时选有相同大质因子相同的数)

注意,这里的 \(s1,s2\) 只压缩了“小质因子”。

然后假设当前枚举到第 \(i\) 个数,其所有小质因子的压缩为 \(s_i\),有转移

\[\begin{aligned}
f1_{s1 \cup s_i,s2} \gets f1_{s1 \cup s_i,s2}+f1_{s1,s2},s2\cap s_i=\varnothing \\
f1_{s1 ,s2\cup s_i} \gets f1_{s1 ,s2\cup s_i}+f1_{s1,s2},s1\cap s_i=\varnothing
\end{aligned}
\]

然后设 \(dp_{s1,s2}\) 在大质因子不同的阶段间转移。每次一个阶段时将 \(dp\) 复制进 \(f1,f2\) 中,结束时用 \(f1,f2\) 更新 \(dp\) 即可。具体而言,结束时有

\[dp_{s1,s2}\gets f1_{s1,s2}+f2_{s1,s2}-dp_{s1,s2}
\]

减掉一个 \(dp\) 是为了减掉重复的情况。答案就是 \(dp\) 的和。

code

注意可能有数没有质因子大于 \(\sqrt n\)。发现这个时候其质因子个数必定小于等于 \(8\),因此直接在 \(dp\) 数组上用暴力做即可。

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=505;
int n,p,pri[N]={2,3,5,7,11,13,17,19},dp[N][N],f1[N][N],f2[N][N];
struct node{int s,mp;}a[N];
bool cmp(node x,node y){return x.mp<y.mp;}
void add(int &x,int y){x=(x+y+p)%p;}
signed main(){
ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
cin>>n>>p;
for(int i=2;i<=n;i++){
int tmp=i;
for(int j=0;j<8;j++){
while(tmp%pri[j]==0) tmp/=pri[j],a[i].s|=(1<<j);
}
a[i].mp=tmp;
}
sort(a+2,a+n+1,cmp);int tl=2,tr=2;dp[0][0]=1;
while(a[tr+1].mp==1) tr++;
for(int i=tl;i<=tr;i++){
for(int s1=255;s1>=0;s1--) for(int s2=255;s2>=0;s2--){
if((s2&a[i].s)==0) add(dp[s1|a[i].s][s2],dp[s1][s2]);
if((s1&a[i].s)==0) add(dp[s1][s2|a[i].s],dp[s1][s2]);
}
}
for(int l=tr+1,r;l<=n;){
r=l;while(a[r].mp==a[r+1].mp) r++;
for(int s1=255;s1>=0;s1--) for(int s2=255;s2>=0;s2--) f1[s1][s2]=dp[s1][s2],f2[s1][s2]=dp[s1][s2];
for(int i=l;i<=r;i++)for(int s1=255;s1>=0;s1--) for(int s2=255;s2>=0;s2--){
if((s2&a[i].s)==0) add(f1[s1|a[i].s][s2],f1[s1][s2]);
if((s1&a[i].s)==0) add(f2[s1][s2|a[i].s],f2[s1][s2]);
}
for(int s1=255;s1>=0;s1--) for(int s2=255;s2>=0;s2--) (dp[s1][s2]=f1[s1][s2]+f2[s1][s2]-dp[s1][s2]+p)%=p;
l=r+1;
}
int ans=0;
for(int s1=255;s1>=0;s1--) for(int s2=255;s2>=0;s2--) (ans+=dp[s1][s2])%=p;
cout<<ans<<'\n';return 0;
}

P2150 [NOI2015] 寿司晚宴 题解的更多相关文章

  1. BZO4197 & 洛谷2150 & UOJ129:[NOI2015]寿司晚宴——题解

    https://www.lydsy.com/JudgeOnline/problem.php?id=4197 https://www.luogu.org/problemnew/show/P2150 ht ...

  2. UOJ #129 / BZOJ 4197 / 洛谷 P2150 - [NOI2015]寿司晚宴 (状压dp+数论+容斥)

    题面传送门 题意: 你有一个集合 \(S={2,3,\dots,n}\) 你要选择两个集合 \(A\) 和 \(B\),满足: \(A \subseteq S\),\(B \subseteq S\), ...

  3. 并不对劲的bzoj4197:loj2131:uoj129:p2150:[NOI2015]寿司晚宴

    题目大意 有两个集合\(S_1,S_2 \subseteq [2,n] (n\leq 500)\),且对于\(\forall x\in S_1,y\in S_2 , gcd(x,y)=1\) 求\(S ...

  4. 洛谷$P2150\ [NOI2015]$寿司晚宴 $dp$

    正解:$dp$ 解题报告: 传送门$QwQ$. 遇事不决写$dp$($bushi$.讲道理这题一看就感觉除了$dp$也没啥很好的算法能做了,于是考虑$dp$呗 先看部分分?$30pts$发现质因数个数 ...

  5. p2150 [NOI2015]寿司晚宴

    传送门 分析 我们发现对于大于$\sqrt(n)$的数每个数最多只会包含一个 所以我们把每个数按照大质数的大小从小到大排序 我们知道对于一种大质数只能被同一个人取 所以f1表示被A取,f2表示被B取 ...

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

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

  7. [UOJ#129][BZOJ4197][Noi2015]寿司晚宴

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

  8. BZOJ 4197: [Noi2015]寿司晚宴 状态压缩 + 01背包

    4197: [Noi2015]寿司晚宴 Time Limit: 10 Sec  Memory Limit: 512 MB Description 为了庆祝 NOI 的成功开幕,主办方为大家准备了一场寿 ...

  9. [BZOJ4197][Noi2015]寿司晚宴

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

  10. BZOJ 4197: [Noi2015]寿司晚宴( dp )

    N^0.5以内的质数只有8个, dp(i, j, k)表示用了前i个大质数(>N^0.5), 2人选的质数(<=N^0.5)集合分别为j, k时的方案数. 转移时考虑当前的大质数p是给哪个 ...

随机推荐

  1. 5分钟搞定!用比扬云SD-WAN远程访问飞牛NAS全攻略

    作为一个NAS重度用户,我最近遇到了一个头疼的问题:如何在外部安全地访问家里的飞牛NAS?经过一番摸索,我发现比扬云SD-WAN是个不错的解决方案,今天就来分享我的实战经验. 一.为什么选择比扬云SD ...

  2. 当向json数组追加节点时,再去修改它,发现所有的该节点的数据都被修改了

    当向一个json数组追加的节点被修改时,所有对象的的节点都被修改了 众所周知,追加json节点时,我们通常会直接给不存在的节点赋值 比如这样: let json = [ { id:'1' }, { i ...

  3. 甲壳虫ADB助手-让你轻松不用电脑就能卸载电视自带软件

    甲壳虫ADB助手是一款非常使用的安卓ADB调试工具,它适用于各种安卓系统设备,包括手机.平板.手表和电视等等,可以帮助用户直接在手机上对设备进行ADB调试,而且不需要ROOT,支持无线配对连接,让用户 ...

  4. QQ/微信域名防红方法,打开网站跳转浏览器打开

    简单通用QQ/微信跳转浏览器打开代码 使用方法: 将代码全部复制 粘贴到 网站根目录下index.php文件的顶端 注意:不要覆盖了 index.php里面的原代码,原代码保留(请尽快把样式以及图片本 ...

  5. Spark 广播变量(broadcast)更新方法

    Spark 广播变量(broadcast)更新方法更新方法spark 广播变量可以通过unpersist方法删除,然后重新广播 val map = sc.textFile("/test.tx ...

  6. AI与.NET系列文章之三:在.NET中使用大语言模型(LLMs)

    引言 在技术迅猛发展的今天,大语言模型(Large Language Models, LLMs)已成为人工智能领域的核心驱动力之一.从智能对话系统到自动化内容生成,LLMs的应用正在深刻改变我们的工作 ...

  7. ascci 码表

  8. RedisTemplate实现setnx分布式锁

    redis工具类 `package com.ttsx.activity.item.services.utils; import lombok.extern.slf4j.Slf4j; import or ...

  9. 【vscode】vscode配置汇编环境

    [vscode]vscode配置汇编环境 前言 ‍ 因为近来个人的课程涉及到汇编语言,加上个人目前是个vscode的重度使用者,所以,要捣鼓一下汇编的配置. 自然,有很多博客写过如何配置,但是每个人在 ...

  10. 在Proxmox VE pve中安装windows操作系统——以ltsc2019为例

    pve创建ltsc2019还是比较简单的.只是没有virtio驱动的话,选择磁盘的时候找不到磁盘.这里主要是列出如何加载virtio驱动 1.创建虚拟机忽略.注意需要新建2个CDROM.一个为wind ...