最近Mayuyu遇到个神奇的数论题目,Mayuyu能做出来真的不容易啊,描述如下。
题目:给定一个正整数,满足条件
,以
为根节点进行扩展,对于每一个节点
,它只能到达能整除
它的节点,如果存在节点
,使得
成立,则必定会经过
点,对于每一个节
点,有一个值,这个值等于这个节点的最大深度,最后求输出每个节点的序号乘对应
值的和。
分析:对于一个数,它只能到达它的所有因子,所以第一步就是找出
的所有因子,然后就是如果两个因子出现一
个能整除另一个的情况,就连一条边。最后就构建了一个图,在这个图中,我们从开始进行深度遍历,纪录
到达点的最大深度值,最后加起来就可以了。这里采用链式前向星处理。
代码:
#include <iostream>
#include <string.h>
#include <algorithm>
#include <stdio.h>
#include <math.h>
using namespace std;
const int N = 5005;
typedef long long LL;
int ct,cnt;
LL fac[N];
int head[N];
struct Edge
{
int to;
int next;
int w;
};
Edge edge[N*N];
void Init()
{
cnt = 0;
memset(edge,0,sizeof(head));
memset(head,-1,sizeof(head));
}
void add(int u,int v,int w)
{
edge[cnt].to = v;
edge[cnt].next = head[u];
edge[cnt].w = w;
head[u] = cnt++;
}
void Find(LL n)
{
ct = 0;
LL t = (LL)sqrt(1.0*n);
for(int i=1; i<=t; i++)
{
if(n % i == 0)
{
if(i * i == n) fac[ct++] = i;
else
{
fac[ct++] = i;
fac[ct++] = n / i;
}
}
}
}
void dfs(int u,int dept)
{
for(int i=head[u]; ~i; i=edge[i].next)
{
int t = edge[i].to;
edge[t].w = max(edge[t].w, dept + 1);
dfs(t,dept+1);
}
}
int main()
{
LL n;
while(cin>>n)
{
Find(n);
Init();
sort(fac,fac+ct);
for(int i=0; i<ct; i++)
{
for(int j=i+1; j<ct; j++)
if(fac[j] % fac[i] == 0)
add(j,i,0);
}
dfs(ct-1,1);
LL ans = 0;
for(int i=0; i<ct; i++)
ans += edge[i].w * fac[i];
cout<<ans + n<<endl;
}
return 0;
}