夏令营501-511NOIP训练16——数字转换
2024-09-08 16:09:45
传送门:QAQQAQ
题意:如果一个数x的约数和(不包括它本身,下同)比它本身小,那么x可以变成它的约数和;如果对于某个y>x且y的约数和为x,那么x也可以变成y。例如,4可以变为3,1可以变为7。限定所有的数字变换在不超过n的正整数范围内进行,求不断进行数字变换且没有重复数字出现的最多变换步数。
思路:YY一下,若$x$可以变为$y$,则$y$也一定能变为$x$,所以我们对于可以互相变换的点建一条无向边,因为每一个点最多之和一个值比它小的点连边,所以不可能出现环(这点可以人工YY证明)
所以我们在这个无环“森林”中跑一个最长链即可
代码:(其实以1为根跑直径不够严谨,用DP算最长链更好)
#include<bits/stdc++.h>
using namespace std; vector<int> v[];
int d[]; void dfs(int u,int f,int depth)
{
d[u]=depth;
for(int i=;i<(int)v[u].size();i++)
{
if(v[u][i]==f) continue;
dfs(v[u][i],u,depth+);
}
} void init(int n)
{
for(int i=;i<=n;i++)
{
int sum=;
for(int j=;j*j<=i;j++)
{
if(i%j==)
{
sum+=j;
if(j*j!=i&&j!=) sum+=i/j;
}
}
if(sum<i)
{
v[sum].push_back(i);
v[i].push_back(sum);
}
}
// for(int i=1;i<=n;i++)
// {
// cout<<i<<":";
// for(int j=0;j<v[i].size();j++) cout<<v[i][j]<<" ";
// cout<<endl;
// }
} int main()
{
int n; cin>>n;
init(n);
dfs(,-,);
int s=-,maxn=-;
for(int i=;i<=n;i++)
{
if(maxn<d[i])
{
maxn=d[i];
s=i;
}
}
dfs(s,-,);
for(int i=;i<=n;i++)
{
if(maxn<d[i]) maxn=d[i];
}
cout<<maxn<<endl;
return ;
}
最新文章
- C++类型转换函数
- postgresql 服务器端编程之hello word
- 一次蜿蜒曲折的RFID破解之路
- 整合Open vSwitch与DNSmasq为虚拟机提供DHCP功能
- Swift标识符和关键字
- jQuery如何阻止子元素继承父元素事件?
- SKPhysicsBody类
- PLSQL Developer安装(Oracle11g+win7_64bit)
- “MEAN”技术栈开发web应用
- webstrom命令大全
- CentOS6+MySQL5.6二进制安装
- 如何检测浏览器url变化
- Python爬虫入门教程 50-100 Python3爬虫爬取VIP视频-Python爬虫6操作
- win10 vscode使用 智能提示
- 播放器更改语言归属地后Cnario player软件无法启动的问题
- Powershell中显示隐藏文件
- HTML5 元素属性介绍
- 百度前端技术学院-task1.8源代码以及个人总结
- WCF创建简单程序
- centos安装docker-ce shell脚本