zoukankan      html  css  js  c++  java
  • 题解西电OJ (Problem 1003 -最喜欢的数字)--动态规划

    Description

             zyf最喜欢的数字是1!所以他经常会使用一些手段,把一些非1的数字变 成1,并为此得意不已。他会且仅会的两种手段是: 
    1.把某个数m除以某个质数p——当然p必须能整除这个数,即m=m/p 
    2.把某个数m减1,即m=m-1 
    有一天他突发奇想,想把[a,b]区间中所有的数一个一个地变成1,这是一个巨大的无聊的工程,所以他想知道他最少得花多少操作才能达到目 的。

    Input
      输入包含多组数据(1000组数据),EOF结束。
      每组数据以两个整数开头:a,b(0<a<=b<=100000),意义如题意描述。
    Output
      每组数据输出一行,最少操作数。
    Sample Input
    2 3
    3 5
    11 12
    Sample Output
    2
    4
    3
     
    解题思路:
    假设一个数字A的最少操作次数为 res[A], 且可以被 S1,S2....Sk。K个素数整除,那么res[A] = min{res[A-1],res[A/S1],res[A/S2] ... ,res[A/Sk]} + 1
    那么我们可以得到递归的解,但是递归的解决这个问题会有很多次重复计算,比如说res[36] 我们需要计算res[36/3] = res[12] 的结果,res[12]又要求计算res[12/2] = res[6]的结果, 要知道res[36]还需要计算res[36/2]=res[18] 的结果,而计算res[18]需要计算 res[18/3]=res[6] 的结果,因此res[6]需要两次被计算,res[2]和 res[3],需要被更多次计算。
    那么为了避免重复的计算,我们使用动态规划算法,先求出100000以内的素数表,从1开始,每个逐个计算,因为res[1] = 0 ;res[i*所有素数] = 1;因此,计算res[i]的时候,通过比较之前素数相乘得到的结果,以及res[i-1]+1的结果进行更新,就能得到res[i]的值。
     
    代码如下:
     1 #include <iostream>
     2 #include "math.h"
     3 using namespace std ;
     4 
     5     int res[100001] ;
     6     bool sieve[100001] = {0};
     7     int prime[10000] ;
     8 
     9 int main()
    10 {
    11 
    12 
    13     int a,b,i,j,k;
    14     int prime_length = 0 ;
    15     for( i = 2 ; i < 100001 ; i++){ // get prime list
    16         if(sieve[i] == false){
    17             prime[prime_length++] = i ;
    18             res[i] = 1 ;
    19             for( j = 2 ; j * i <= 100000 ; j++){
    20                 sieve[i*j] = true;
    21             }
    22         }
    23     }
    24     res[0] = res[1] =0 ;
    25     res[2] = res[3] = 1 ;
    26     for(i = 2 ; i < 100001 ; i++ ){   //DP get res[num]
    27         if(res[i] == 0 || res[i-1] < res[i]-1 ){
    28             res[i] = res[i-1] + 1 ;
    29         }
    30         for(j = 0 ; j < prime_length && i * prime[j] < 100001 ; j++){
    31             if(res[i*prime[j]] == 0 || (res[i]+1) < res[i*prime[j]]){
    32                 res[i*prime[j]] = res[i] + 1;
    33             }
    34         }
    35     }
    36 
    37     while(cin>>a>>b){
    38 
    39     
    40         j = 0;
    41         for(i = a ; i <= b ;i++){
    42             j += res[i] ;
    43         }
    44         cout << j << endl;
    45     }
    46 }
     
     
     
  • 相关阅读:
    Angular Universal 学习笔记
    SAP Spartacus 如何获得当前渲染页面的 CMS 元数据
    Angular 服务器端渲染的学习笔记(二)
    Angular 服务器端渲染的学习笔记(一)
    第三方外部 Saas提供商如何跟使用 SAP 系统的客户进行对接接口集成
    如何从 SAP Spartacus Product Detail 页面,找到其 Angular 实现 Component 的位置
    具备自动刷新功能的 SAP ABAP ALV 报表
    C++学习目录
    c--条件编译
    c--文件读写--二进制
  • 原文地址:https://www.cnblogs.com/liucheng/p/3683254.html
Copyright © 2011-2022 走看看