帮忙分析一个c++试题,算法方面的。程序有了,特别是solve() 函数,理解不了,帮忙分析一下吧

问题描述
如果一个数x的约数和(不包括它本身,下同)比它本身小,那么x可以变成它的约数和;如果对于某个y>x且y的约数和为x,那么x也可以变成y。例如,4可以变为3,1可以变为7。限定所有的数字变换在不超过n的正整数范围内进行,求不断进行数字变换且没有重复数字出现的最多变换步数。

输入数据
输入一个正整数n。

输出数据
输出最少需要花费的时间。

样例输入
7

样例输出
3

样例说明
一种方案为:4→3→1→7。

时间限制
各测试点1秒

内存限制
你的程序将被分配32MB的运行空间

数据范围
n<=50 000。

#include <fstream>
using namespace std;
ifstream fin("44.in") ;
ofstream fout("44.out");
long f1[50000],f2[50000];
long sum[50000];
long n;
void init()
{
for(long i=1;i<=n;i+=1)
{
long t;
t=i*2;
while(t<=n)
{
sum[t]+=i;
t+=i;

}

}
}

void solve()
{
for(int i=n;i>=1;i-=1)
{
long t=sum[i];
if(t>=i) continue;
if(f1[i]+1>f1[t])
{
f2[t]=f1[t];
f1[t]=f1[i]+1;

}
else if(f1[i]+1>f2[t])
{
f2[t]=f1[i]+1;
}

}
}
void print()
{
long max=0;

for(long i=1;i<=n;i++)
{
if(f1[i]+f2[i]>max)
{
max=f1[i]+f2[i];
}

}
fout<<max;
}

int main()
{
fin>>n;
init();
solve();
print();
}
f1 f2这两个数组是做什么的。具体怎么回事呢

首先我们知道一条可行方案必定是一条链而不可能是一个环
那么所有可进行变化的数之间连边就是一棵树,我们要求这棵树里最长链.
那么就是一个树形dp,每个点记录以他为一端的最长链和次长链。
最后枚举每个点,看经过哪个点的连最长即为答案.
f1为最长链,f2为次长链追问

if(f1[i]+1>f1[t])
{
f2[t]=f1[t];
f1[t]=f1[i]+1;
}
else if(f1[i]+1>f2[t])
{
f2[t]=f1[i]+1;
}
这一句怎么解析?

追答

t 是 i 的 父亲
if f1[i]+1>f1[t] 即是说如果用i来更新t的最长链和次长链时发现这个结果比最长链更优,就把原来的最长链赋值给次长链,最长链为新的值,否则如果新的值大于次长链,则把新的值赋给次长链

追问

max=f1[i]+f2[i];
这是不是把最长链和次长链加起来了? 是什么意思。。麻烦你了。我第一次接触这个东西。可以多给你一些分

追答

不好意思,我没有说清楚,这里的最长链和次长链均是指以该点为一端的最长链和次长链,因此最长链和次长链接起来就是以该点为根的子树里,经过这个点的最长的一条链.

温馨提示:内容为网友见解,仅供参考
无其他回答

...程序有了,特别是solve() 函数,理解不了,帮忙分析一下吧
for(int i=n;i>=1;i-=1) 这个 从 n~ 1 不等价的 注意下标是的整个算法就计算方式不同了, 你该了这一句,里面的语句比如t>=i 也得相应修改啊,

C++中关于二义性问题,,请帮忙分析下面的程序...
原因在于继承得到的成员函数没有构成派生类中的重载函数列表,具有相同名称函数只在同一类域 或 全局域中构成重载

一个简单的c++程序,请帮忙分析一下(输入输出格式控制方面)
你可能是希望这一行按10进制输出而非8进制,但由于操作符对流格式的控制是通过修改流的标志位来实现的,所以在你源代码的第10行(包括空行)cout<<"i= "<<oct<<i<<endl; 中,流对象cout中的标志位已经被修改,所以它在下一次输出的时候使用的就是已经被修改后的标志位来进行格式输出,也就是八...

各位帮忙看一下,我这程序哪里出了错误?
一、应用程序没有检查内存分配失败 程序需要一块内存用以储存数据时,就需要使用操作系统提供的「功能函数」来申请,如果内存分配成功,函数就会将所新开辟的内存区地址返回给应用程序,应用程序就可以通过这个地址使用这块内存。这就是「动态内存分配」,内存地址也就是编程中的「光标」。内存不是永远都招之即来、用之不...

最近总是出现程序没有响应的问题,请高手帮忙分析一下
1.如果能打开任务管理器的话,去检查一下哪一个进程占用了较多的CPU资源和内存。2.找到了之后就结束这个进程,看一下是否恢复了正常。PS:NOD32不是很好,我用了一下之后就删除了。如果是它的问题那么就卸载它,换一个杀毒软件,杀毒软件用个正版的费用不是很高的。好马配好鞍哈。

帮忙分析个程序,很是苦恼啊feof函数究竟什么意思啊fgets呢能帮忙把els...
int feof( FILE *stream );是测试stream所指的文件描述符是否到了文件结尾 char *fgets( char *string, int n, FILE *stream );是从stream所指的文件的当前位置读取一行到string所指向的字符串中(包括\\n符),如果一直没有发现新行符,则最多读取第二个参数n-1个字符到字符串中。else { while...

大哥大姐帮忙看这是什么问题~~~ 谢谢了
(0x后面内容有可能不一样。) 散一般出现这个现象有方面的,一是硬件,即内存方面有问题,二是软件,这就有多方面的问题了。 1、微软IE缓冲溢出漏洞引起 2、内存或虚拟内存地址使用冲突造成程序的运行需要分配一定的内存地址给程序使用,当程序结束时释放留出空间让给新的程序使用,win是多任务的系统有时前程序未结束 ...

...详细 (x=3,y=4,y++,y-x)这个情况高手们帮忙分析一下,谢谢_百度...
一般情况下,在一段程序里面,x++是先使用x的值再将x加一,++x是先将x加一在使用!楼主注意是一段程序,有先后顺序的,比如(x=3,y=4,y++,y-x)这种情况,括号里面就是一段程序,y加完1之后再用。提醒,括号里面的算法是从做到右计算的。这种情况下经过y++后y=5,然后在计算y-x,但是最后...

帮忙分析一个句子结构,谢谢大家
这句翻译成:“这样可能得不到在公司方面的理解,还可能成为晋升的障碍。”“会社での理解”说的是在公司里获得的理解,这里公司是一个范围,也不只是指某个实体。就是说这种做法在公司工作的过程中,或者在公司里面,等等的一个概念上得到理解。有一个“在公司里面,在公司方面”的意思。而不是说...

c++关于switch case 中case问题
对于有些程序可以倒过来,比如,课本上常见的根据成绩来判断成绩等级的那一串代码就可以倒过来。但对这一个程序来说,不可以。在课本上我们都学过,一个程序一般上都是顺序执行的(函数调用或者用了goto转向语句的例外)。这个程序的算法便是妙用了这一思想。执行完一个case语句后,如果没遇到break,程...

相似回答