P7091 数上的树
首先将 \(n\) 分解质因数,用 DFS 求出 \(n\) 的所有因数,记为 \(d_1,d_2,\cdots,d_c\),跑一遍反素数那题的代码可知 \(c\leq 23327\)(
设 \(f_i\) 表示根节点为 \(d_i\) 时最小值。
显然,局部最优值可以保证整体最优值,且转移无后效性,即求 \(f_i\) 时不会影响 \(f_j\ (d_j<d_i)\),故答案可以用树形 DP 求出,将所有因数排序后可以转化为序列上的 DP。
对于不能出现在树上的 \(d_i\) 直接 skip 即可。
设 \(g_i\) 表示 \(d_i\) 所含有的质因子个数。For example,\(12=2\times 2\times 3\),所以 \(12\) 有 \(3\) 个质因子。在本题中,\(g_{i}\) 也表示以 \(d_i\) 为根的子树的节点个数,不难发现其为定值。
假设当前转移 \(f_i\) 决策点为 \(j,k\ (d_j\times d_k=d_i)\),那么对于 \(d_j\) 和 \(d_k\) 子树内两两组合出的 pairs 的贡献可以直接由 \(f_j+f_k\) 推得,剩下来只有两种情况:
- Case 1:\(d_j\) 和 \(d_k\) 子树内各一个节点组合出的 pairs。因为它们的 LCA 是 \(d_i\),且共有 \(g_j\times g_k\) 对 pairs,故贡献为 \(g_j\times g_k\times d_i\)。
- Case 2:\(d_i\) 和任意一个节点组合出的 pairs。显然贡献为 \(g_i\times d_i\)。
转移方程:
\]
,其中 \(g_i=g_j+g_k+1\) 可以在 DP 时一并求出。
这样子搞是 \(\mathcal O(c^3)\) 的,显然无法接受。
- 剪枝 1:在枚举内层循环 \(j\) 时发现 \(k\) 有单调性,所以直接用 pointer 代替 \(k\) 即可。这样时间复杂度降为了 \(\mathcal O(c^2)\)。
- 剪枝 2:当 \(j>k\) 时直接 break,减小常数。
综上,我们有了一个 \({\mathcal O}(\sqrt n+m\log c+c^2)\) 的算法(分解质因数 + 处理限制需要二分查找 + DP),代码如下:
ll n,m,num[N],f[N];
ll cnt,pr[N],c[N],tot;
ll fc[N],il[N],d;
map <ll,int> isp;
void dfs(int pos,ll prod){
if(pos>cnt){
if(prod>1)fc[++d]=prod;
return;
} for(int i=0;i<=c[pos];i++)dfs(pos+1,prod),prod*=pr[pos];
}
int main(){
cin>>n>>m;
// factor
ll tmp=n;
for(ll i=2;i*i<=n;i++)
if(n%i==0){
pr[++cnt]=i,isp[i]=1;
while(n%i==0)c[cnt]++,tot++,n/=i;
}
if(n>1)pr[++cnt]=n,tot++,c[cnt]=1,isp[n]=1;
n=tmp;
// find factors
dfs(1,1);
sort(fc+1,fc+d+1);
// limit
for(int i=1;i<=m;i++){
ll val=read();
int pos=lower_bound(fc+1,fc+d+1,val)-fc;
if(pos<=d&&fc[pos]==val)il[pos]=1; // 表示 pos 不能出现
}
// dp
for(int i=1;i<=d;i++){
if(il[i])continue;
if(isp[fc[i]]){
num[i]=1,f[i]=fc[i];
continue;
} il[i]=1,f[i]=inf; // 如果无法由以前的 j,k 转移得到那么 i 也无法得到
int p=i-1;
for(int j=1;j<i;j++){
if(fc[i]%fc[j])continue;
while(fc[p]>fc[i]/fc[j])p--;
if(j>p)break;
if(!il[j]&&!il[p])f[i]=min(f[i],f[j]+f[p]+num[j]*num[p]*fc[i]+(num[i]=num[j]+num[p]+1)*fc[i]),il[i]=0;
}
} if(il[d])puts("-1");
else cout<<(ll)f[d]<<endl;
return 0;
}
P7091 数上的树的更多相关文章
- [Swust OJ 746]--点在线上(线段树解法及巧解)
题目链接:http://acm.swust.edu.cn/problem/746/ Time limit(ms): 1000 Memory limit(kb): 65535 fate是一个数学大牛 ...
- [BJOI2019]删数(线段树)
[BJOI2019]删数(线段树) 题面 洛谷 题解 按照值域我们把每个数的出现次数画成一根根的柱子,然后把柱子向左推导,\([1,n]\)中未被覆盖的区间长度就是答案. 于是问题变成了单点修改值,即 ...
- 【BZOJ4408】[FJOI2016]神秘数(主席树)
[BZOJ4408][FJOI2016]神秘数(主席树) 题面 BZOJ 洛谷 题解 考虑只有一次询问. 我们把所有数排个序,假设当前可以表示出的最大数是\(x\). 起始\(x=0\). 依次考虑接 ...
- BZOJ_2120_数颜色_Set+树状数组+主席树
BZOJ_2120_数颜色_Set+树状数组+主席树 Description 墨墨购买了一套N支彩色画笔(其中有些颜色可能相同),摆成一排,你需要回答墨墨的提问.墨墨会像你发布如下指令: 1. Q L ...
- 【2019.7.25 NOIP模拟赛 T3】树(tree)(dfs序列上开线段树)
没有换根操作 考虑如果没有换根操作,我们该怎么做. 我们可以求出原树的\(dfs\)序列,然后开线段树维护. 对于修改操作,我们可以倍增求\(LCA\),然后在线段树上修改子树内的值. 对于询问操作, ...
- P3939 数颜色 线段树动态开点
P3939 数颜色 线段树动态开点 luogu P3939 水.直接对每种颜色开个权值线段树即可,注意动态开点. #include <cstdio> #include <algori ...
- Jmeter任在运行,线程数上不去
问题 jmeter在运行,但是线程数上不去(本来模型设计了100个总线程,但运行时线程只能上到5,根据图上观察总共也只能运行5个线程) 之前更新了random csv插件 解决办法 查看jmeter. ...
- [BZOJ4408&&BZOJ4299][FJOI2016 && Codechef]神秘数&&FRBSUM(主席树)
4299: Codechef FRBSUM Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 550 Solved: 351[Submit][Statu ...
- BZOJ2120 数颜色(树套树)
B. 数颜色 题目描述 墨墨购买了一套N支彩色画笔(其中有些颜色可能相同),摆成一排,你需要回答墨墨的提问.墨墨会像你发布如下指令:1. Q L R代表询问你从第L支画笔到第R支画笔中共有几种不同颜色 ...
随机推荐
- 【UE4 C++ 基础知识】<13> 多线程——TaskGraph
概述 TaskGraph 系统是UE4一套抽象的异步任务处理系统 TaskGraph 可以看作一种"基于任务的并行编程"设计思想下的实现 通过TaskGraph ,可以创建任意多线 ...
- js判断移动端浏览器类型,微信浏览器、支付宝小程序、微信小程序等
起因 现在市场上各种跨平台开发方案百家争鸣各有千秋,个人认为最成熟的还是hybird方案,简单的说就是写H5各种嵌入,当然作为前端工程师最希望的也就是公司采用hybird方案当作技术路线. 所谓的hy ...
- Noip模拟67 2021.10.3
还是困,不过已经可以用脑子思考问题了 T1 数据恢复 没啥明确的算法,可以说是贪心? 考虑部分分, 链的直接扫, 对于菊花的发现只要根节点在第一个,剩下的点位置不重要 那么按照$a/b$排序,扫一遍就 ...
- 常用Java API:HashMap 和 TreeMap
摘要 本文主要介绍Map接口下的HashMap和TreeMap. HashMap HashMap是基于哈希表的 Map 接口的实现,是无序的 clear()//清空. containsKey(Obje ...
- Python课程笔记(十)
不陌生,之前学习一个开源SpringBoot项目,Mysql5.5更换到5.7搞得头疼. 数据库连接的坑之前写的IDEA系列连接会遇到的问题.课程代码 今天上课就主要学习了python如何连接mysq ...
- Vulnhub实战-dr4g0n b4ll靶机👻
Vulnhub实战-dr4g0n b4ll靶机 地址:http://www.vulnhub.com/entry/dr4g0n-b4ll-1,646/ 描述:这篇其实没有什么新奇的技巧,用到的提权方式就 ...
- (继承)Program2.1
覆盖和重写的意思是一样?结果是一样的 例如: 1 class Parent: # 定义父类 2 def myMethod(self): 3 print('调用父类方法') 4 5 6 class Ch ...
- AtCoder Beginner Contest 182 F
F - Valid payments 简化题意:有\(n\)种面值的货币,保证\(a[1]=1,且a[i+1]是a[i]的倍数\). 有一个价格为\(x\)元的商品,付款\(y\)元,找零\(y-x\ ...
- Mac 搭建后端PHP+Go环境
准备工作 1. 安装brew命令 #很慢很慢.. ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/insta ...
- Linux&C open creat read write lseek 函数用法总结
一:五个函数的参数以及返回值. 函数 参数 返回值 open (文件名,打开方式以及读 ...