zoukankan      html  css  js  c++  java
  • 数字转换

    https://loj.ac/problem/10155

    题目描述

      一个数的约数和(不包括它本身)如果比这个数小,那么这个数可以转移到这个数的约数和,这个约数和也可以变为这个数,所有操作在(n)的范围内进行,求最多不经过重复步数的操作。

    思路

      我们考虑如果(x)可以变成(y),那么我们在(x)(y)之间连边,那么最后的图一定会是一棵以(1)为根的树和一些骨裂节点,因为所有质数必定可以转移到(1),而所有的合数必定会有一种方式变小,直到为(1)。那么题目就相当于求树上最长链。我们考虑最长的链必定会是在以某一个节点为根的两个叶子节点的路径,所以我们为维护两个数组(d1)(d2)表示以这个点为根到叶子节点的最长距离和次长距离即可。

    代码

    #include <bits/stdc++.h>
    using namespace std;
    
    int read()
    {
    	int res=0,w=1;
    	char ch=getchar();
    	while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
    	while(ch>='0'&&ch<='9'){res=(res<<3)+(res<<1)+(ch^48);ch=getchar();}
    	return res*w;
    }
    void write(int x)
    {
    	if(x<0){putchar('-');x=-x;}
    	if(x>9)write(x/10);
    	putchar(x%10+'0');
    }
    
    int a[50005],d1[50005],d2[50005];
    int main() 
    {
    	int n=read();
    	for(int i=1;i<=n;i++)
    		for(int j=2;j<=n/i;j++)
    			a[i*j]+=i;
    	for(int i=n;i>=1;i--)
    		if(i>a[i])
    		{
    			if(d1[i]+1>d1[a[i]])
    			{
    				d2[a[i]]=d1[a[i]];
    				d1[a[i]]=d1[i]+1;
    			}
    			else if(d1[i]+1>d2[a[i]])d2[a[i]]=d1[i]+1;
    		}
    	int ans=0;
    	for(int i=1;i<=n;i++)
    		ans=max(ans,d1[i]+d2[i]);
    	write(ans);
    }
    
  • 相关阅读:
    6-[多线程]-互斥锁、GIL、死锁、递归锁、信号量
    5-[多线程]-线程理论
    4-1 多进程练习题
    压缩与解压缩
    检测SSL证书很好用的三个网站
    shell之sort和uniq 及wc 的使用
    shell之cut和tr 的命令的使用
    三剑客之awk数组实战
    三剑客之sed
    linux文件查找(find,locate)
  • 原文地址:https://www.cnblogs.com/fangbozhen/p/11838284.html
Copyright © 2011-2022 走看看