• UVA10791-Minimum Sum LCM(唯一分解定理基本应用)


    原题:https://vjudge.net/problem/UVA-10791

    基本思路:1、借助唯一分解定理分解数据。2、求和输出

    知识点:1、筛法得素数 2、唯一分解定理模板代码 3、数论分析-唯一分解定理的性质

    唯一分解定理:该定理通过素数将任意一个大于2的n分解为 最小质数因子的幂 的乘积。这是一个数字简化的过程。

    题目易错点在于要求得到的是 ‘n的多个因子的和’,且该多个因子的最小公倍数为n。是多个,而不是两个!!由此看来,其实如果把分解定理得到的每一个‘质数^指数’的形式看作一个整数元素,那么,由n所得到的所有元素的最小公倍数恰好是n,因为每个元素的底数是素数。所以,‘最小的和’应当是‘所有整数元素的和’。

    代码如下:

     1 #include<iostream>
     2 #include<cstring>
     3 #include<cstdio>
     4 #include<algorithm>
     5 #include<cmath>
     6 using namespace std;
     7 typedef long long LL;
     8 const int maxn = 100000;
     9 int prime[maxn];
    10 int dn[1000],zn[1000];
    11 LL psd[1000];
    12 int num=1;
    13 
    14 int pre()//筛法出素数
    15 {
    16     memset(prime,0,sizeof(prime));
    17     prime[0]=prime[1]=1;
    18     for(int i=2;i<sqrt(maxn);i++)
    19     {
    20         if(prime[i])continue;
    21         for(int j=2*i;j<maxn;j+=i)prime[j]=1;
    22     }
    23     return 0;
    24 }
    25 
    26 int decomposition(int n)
    27 {
    28     memset(dn,0,sizeof(dn));
    29     memset(zn,0,sizeof(zn));
    30     int cur=0;
    31     //
    32     if(n==1)return 1;
    33     for(int k=2;k<maxn;k++)
    34     {
    35         bool ok=false;
    36         if(prime[k]==1)continue;//不是素数就不作为因子
    37         while(n%k==0)
    38         {
    39             n/=k;
    40             dn[cur]=k;
    41             zn[cur]++;
    42             ok=true;
    43         }
    44         if(ok)cur++;//cur表示到目前为止的因子个数
    45         if(n==1)break;
    46     }
    47     if(n!=1){dn[cur]=n;zn[cur++]=1;}//最终n会变成1或者一个大质数
    48     return cur;//返回因子的总个数
    49 }
    50 
    51 LL change(int lenth)
    52 {
    53     LL m=0;
    54     for(int i=0;i<lenth;i++)
    55         m+=pow(dn[i],zn[i]);
    56     return m;
    57 }
    58 
    59 int solve(int n)
    60 {
    61     int lenth=decomposition(n);
    62     printf("Case %d: ",num++);
    63     if(lenth==1)
    64     {
    65         printf("%lld
    ",n+1);
    66         return 0;
    67     }
    68     printf("%lld
    ",change(lenth));
    69     return 0;
    70 }
    71 
    72 int main()
    73 {
    74     pre();
    75     int n;
    76     while(scanf("%d",&n)&&n)solve(n);
    77     return 0;
    78 }

    这一定不是最简单的算法,因为我们并不能很好的计算maxn适用的最小值,这在一定程度上浪费了一定的计算力和时间。不过对应付UVA的测试来说足矣。

    至于更为简单的算法,我会在参考其他大神的代码后写在我的后续博客里。

  • 相关阅读:
    领域驱动设计实践,精通业务,面向对象编程,面条编程,过程编程
    日志聚合与全链路监控
    Spring Security OAuth2 之token 和 refresh token
    Web开发技术发展历程(笔记)
    JDBC 数据处理 总结
    Idea创建Maven多模块项目
    中国 / 省市区县 / 四级联动 / 地址选择器(京东商城地址选择)
    左膀mongostat,右臂mongotop——MongoDB的监控之道
    制定项目章程
    挣值分析
  • 原文地址:https://www.cnblogs.com/savennist/p/12245837.html
Copyright © 2020-2023  润新知