题目传送门


分析

最小公倍数最终一定会被表示成若干个质数指数幂的情况(1的情况就直接乘上二的次幂)

然后每个数的加入相当于对每个质数的指数取最大值,但是如果将每个质数的次数都表示出来状态数很多,

考虑根号分治,只将 \(2,3,5,7,11,13,17\) 的情况处理出来,然后之后的质数幂次直接滚动数组就可以了。


代码

#include <cstdio>
#include <cctype>
#include <cstring>
#include <algorithm>
using namespace std;
const int N=301,mx[7]={9,6,4,3,3,3,3};
const int prime[62]={2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,103,107,109,113,127,131,137,139,149,151,157,163,167,173,179,181,191,193,197,199,211,223,227,229,233,239,241,251,257,263,269,271,277,281,283,293};
int n,mod,ans,tot,c[N],a[N][7],b[N],o,rk[N],pw[7][9],p[7],_p[7],two[300011],dp[2][2][9][6][4][3][3][3][3],f[2][9][6][4][3][3][3][3];
int iut(){
int ans=0; char c=getchar();
while (!isdigit(c)) c=getchar();
while (isdigit(c)) ans=ans*10+c-48,c=getchar();
return ans;
}
int max(int a,int b){return a>b?a:b;}
void Mo(int &x,int y){x=x+y>=mod?x+y-mod:x+y;}
bool cmp(int x,int y){return b[x]<b[y];}
int main(){
n=iut(),mod=iut(),two[0]=1;
for (int i=0;i<7;++i){
pw[i][0]=1;
for (int j=1;j<mx[i];++j)
pw[i][j]=1ll*pw[i][j-1]*prime[i]%mod;
}
for (int i=1;i<=n;++i) ++c[iut()],two[i]=(two[i-1]+two[i-1])%mod;
for (int i=2;i<N;++i) if (c[i]) rk[++tot]=i;
for (int i=0;i<62;++i){
for (int j=prime[i];j<N;j+=prime[i])
if (c[j]){
int CNT=0;
for (int x=j;x%prime[i]==0;x/=prime[i],++CNT);
if (i<7) a[j][i]=CNT;
else b[j]=i;
}
}
sort(rk+1,rk+1+tot,cmp),f[0][0][0][0][0][0][0][0]=1;
for (int l=1,r;l<=tot;l=r+1){
for (r=l;r<=tot&&b[rk[r]]==b[rk[l]];++r); --r;
if (l==1&&b[rk[1]]) dp[0][0][0][0][0][0][0][0][0]=1;
if (b[rk[l]]){
for (int i=l;i<=r;++i){
if (!c[rk[i]]) continue;
int t=two[c[rk[i]]]-1;
o^=1,memcpy(dp[o],dp[o^1],sizeof(dp[o]));
for (int j=0;j<7;++j) p[j]=0;
for (int g=0;!g;){
for (int j=0;j<7;++j) _p[j]=max(p[j],a[rk[i]][j]);
int t0=1ll*dp[o^1][0][p[0]][p[1]][p[2]][p[3]][p[4]][p[5]][p[6]]*t%mod;
int t1=1ll*dp[o^1][1][p[0]][p[1]][p[2]][p[3]][p[4]][p[5]][p[6]]*t%mod;
Mo(dp[o][1][_p[0]][_p[1]][_p[2]][_p[3]][_p[4]][_p[5]][_p[6]],t0+t1>=mod?t0+t1-mod:t0+t1);
g=1;
for (int j=6;g&&~j;--j)
p[j]+=g,g=p[j]/mx[j],p[j]%=mx[j];
}
}
for (int j=0;j<7;++j) p[j]=0;
for (int g=0;!g;){
int &t=dp[o][1][p[0]][p[1]][p[2]][p[3]][p[4]][p[5]][p[6]];
Mo(dp[o][0][p[0]][p[1]][p[2]][p[3]][p[4]][p[5]][p[6]],1ll*t*prime[b[rk[l]]]%mod),t=0;
g=1;
for (int j=6;g&&~j;--j)
p[j]+=g,g=p[j]/mx[j],p[j]%=mx[j];
}
}else{
for (int i=l;i<=r;++i){
if (!c[rk[i]]) continue;
int t=two[c[rk[i]]]-1;
o^=1,memcpy(f[o],f[o^1],sizeof(f[o]));
for (int j=0;j<7;++j) p[j]=0;
for (int g=0;!g;){
int now=1ll*f[o^1][p[0]][p[1]][p[2]][p[3]][p[4]][p[5]][p[6]]*t%mod;
if (now){
for (int j=0;j<7;++j) _p[j]=max(p[j],a[rk[i]][j]);
Mo(f[o][_p[0]][_p[1]][_p[2]][_p[3]][_p[4]][_p[5]][_p[6]],now);
}
g=1;
for (int j=6;g&&~j;--j)
p[j]+=g,g=p[j]/mx[j],p[j]%=mx[j];
}
}
}
if (l==1&&!b[rk[1]]){
for (int j=0;j<7;++j) p[j]=0;
for (int g=0;!g;){
dp[0][0][p[0]][p[1]][p[2]][p[3]][p[4]][p[5]][p[6]]=f[o][p[0]][p[1]][p[2]][p[3]][p[4]][p[5]][p[6]];
g=1;
for (int j=6;g&&~j;--j)
p[j]+=g,g=p[j]/mx[j],p[j]%=mx[j];
}
o=0;
}
}
for (int j=0;j<7;++j) p[j]=0;
for (int g=0;!g;){
int t=1ll*pw[0][p[0]]*pw[1][p[1]]*pw[2][p[2]]*pw[3][p[3]]%mod*pw[4][p[4]]*pw[5][p[5]]*pw[6][p[6]]%mod;
Mo(ans,1ll*dp[o][0][p[0]][p[1]][p[2]][p[3]][p[4]][p[5]][p[6]]*t%mod);
g=1;
for (int j=6;g&&~j;--j)
p[j]+=g,g=p[j]/mx[j],p[j]%=mx[j];
}
return !printf("%lld",1ll*ans*two[c[1]]%mod);
}

#根号分治,动态规划#洛谷 5616 [MtOI2019]恶魔之树的更多相关文章

  1. 动态规划 洛谷P1616 疯狂的采药

    动态规划 洛谷P1616 疯狂的采药 同样也是洛谷的动态规划一个普及-的题目,接下来分享一下我做题代码 看到题目,没很认真的看数据大小,我就提交了我的代码: 1 //动态规划 洛谷P1616 疯狂的采 ...

  2. 动态规划 洛谷P1048 [NOIP2005 普及组] 采药

    洛谷P1048 [NOIP2005 普及组] 采药 洛谷的一个谱架-的题目,考的是01背包问题,接下来分享一下我的题解代码. AC通过图: 我的代码: 1 //动态规划 洛谷P1048 [NOIP20 ...

  3. 动态规划 洛谷P4017 最大食物链计数——图上动态规划 拓扑排序

    洛谷P4017 最大食物链计数 这是洛谷一题普及/提高-的题目,也是我第一次做的一题 图上动态规划/拓扑排序 ,我认为这题是很好的学习拓扑排序的题目. 在这题中,我学到了几个名词,入度,出度,及没有环 ...

  4. 洛谷 P3384 【模板】树链剖分-树链剖分(点权)(路径节点更新、路径求和、子树节点更新、子树求和)模板-备注结合一下以前写的题目,懒得写很详细的注释

    P3384 [模板]树链剖分 题目描述 如题,已知一棵包含N个结点的树(连通且无环),每个节点上包含一个数值,需要支持以下操作: 操作1: 格式: 1 x y z 表示将树从x到y结点最短路径上所有节 ...

  5. 洛谷p3384【模板】树链剖分题解

    洛谷p3384 [模板]树链剖分错误记录 首先感谢\(lfd\)在课上调了出来\(Orz\) \(1\).以后少写全局变量 \(2\).线段树递归的时候最好把左右区间一起传 \(3\).写\(dfs\ ...

  6. 点分治模板(洛谷P4178 Tree)(树分治,树的重心,容斥原理)

    推荐YCB的总结 推荐你谷ysn等巨佬的详细题解 大致流程-- dfs求出当前树的重心 对当前树内经过重心的路径统计答案(一条路径由两条由重心到其它点的子路径合并而成) 容斥减去不合法情况(两条子路径 ...

  7. 洛谷 P5518 - [MtOI2019]幽灵乐团 / 莫比乌斯反演基础练习题(莫比乌斯反演+整除分块)

    洛谷题面传送门 一道究极恶心的毒瘤六合一题,式子推了我满满两面 A4 纸-- 首先我们可以将式子拆成: \[ans=\prod\limits_{i=1}^A\prod\limits_{j=1}^B\p ...

  8. 洛谷 P3384 【模板】树链剖分

    树链剖分 将一棵树的每个节点到它所有子节点中子树和(所包含的点的个数)最大的那个子节点的这条边标记为"重边". 将其他的边标记为"轻边". 若果一个非根节点的子 ...

  9. 洛谷P3459 [POI2007]MEG-Megalopolis(树链剖分,Splay)

    洛谷题目传送门 正解是树状数组维护dfn序上的前缀和,这样的思路真是又玄学又令我惊叹( 我太弱啦,根本想不到)Orz各路Dalao 今天考了这道题,数据范围还比洛谷的小,只有\(10^5\)(害我复制 ...

  10. [洛谷P1198/BZOJ1012][JSOI2008] 最大数 - 树状数组/线段树?

    其实已经学了树状数组和线段树,然而懒得做题,所以至今没写多少博客 Description 现在请求你维护一个数列,要求提供以下两种操作: 1. 查询操作. 语法:Q L 功能:查询当前数列中末尾L个数 ...

随机推荐

  1. python字典操作的大O效率

  2. heapq模块通过nlargest()和nsmallest()找到最大或最小的N个元素

    问题 我们想在某个集合中找出最大或最小的N个元素 解决方案 heapq模块中有两个函数nlargest()和nsmallest() import heapq nums = [1,8,2,23,7,-4 ...

  3. 狂神说Git学习笔记整理

    Git 版本控制 ​ 在开发过程中,项目会进行版本迭代,新版本会取代旧版本,但是我们不希望直接删除旧版本,所以就需要一个版本管理器来管理新旧版本,不然就是手动控制... 多人开发必须使用版本控制!!! ...

  4. Android内存优化—内存优化总结

    内存优化总结 内存问题 内存抖动:导致GC导致卡顿 内存泄漏:导致频繁GC,可用内存减少 内存溢出:导致OOM 工具排查 AS中的Profiler查看内存情况,是否锯齿状,是否持续上升 MAT排查 L ...

  5. 【Azure 环境】移动应用 SSO 登录AAD, MSAL的配置为Webview模式时登录页面无法加载

    问题描述 移动端集成MASL登录过程中,配置文件中配置项"authorization_user_agent"使用"DEFAULT"可以正常登录,但是改为&quo ...

  6. 聊聊 HTTP 性能优化

    哈喽大家好,我是咸鱼. 作为用户的我们在 "上网冲浪" 的时候总是希望快一点,尤其是抢演唱会门票的时候,但是现实并非如此,有时候我们会遇到页面加载缓慢.响应延迟的情况. 而 HTT ...

  7. 使用debezium实现cdc实时数据同步功能记录

    Debezium 是一个用于变更数据捕获的开源分布式平台.能够保证应用程序就可以开始响应其他应用程序提交到您数据库的所有插入.更新和删除操作.Debezium 持久.快速,因此即使出现问题,您的应用程 ...

  8. STL-bitset模拟实现

    #include<time.h> #include<string> #include<vector> #include<iostream> using ...

  9. 解决网页无法复制粘贴选中的问题 显示vip无法复制解决方案

    方法:先是按F12打开控制台点击console输入以下代码!!!! 解决网页禁止鼠标右键,无法被选中的 第一种: javascript:(function() { function R(a){ona ...

  10. 微信自动信息发送助手WMR

    某信自动信息发送助手WMR 最近放假闲来无事,捣鼓了一下pyqt5,正好手上有每天定时大量群发消息的需求,正好就用pyqt5做个小应用练练手. 包含到的主要库:pyqt5.pyperclip.pyau ...