最近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; }
数论vs图论
时间: 2024-10-13 22:42:15