动归,sqrt(n)求解约数

来源:互联网 发布:河池论坛 网络问政 编辑:程序博客网 时间:2024/06/05 13:57

题目描述

网易2017校招
小易来到了一条石板路前,每块石板上从1挨着编号为:1、2、3…….
这条石板路要根据特殊的规则才能前进:对于小易当前所在的编号为K的 石板,小易单次只能往前跳K的一个约数(不含1和K)步,即跳到K+X(X为K的一个非1和本身的约数)的位置。 小易当前处在编号为N的石板,他想跳到编号恰好为M的石板去,小易想知道最少需要跳跃几次可以到达。
例如:

N = 4M = 244->6->8->12->18->24

于是小易最少需要跳跃5次,就可以从4号石板跳到24号石板
输入描述:
输入为一行,有两个整数N,M,以空格隔开。
(4 ≤ N ≤ 100000)
(N ≤ M ≤ 100000)

输出描述:
输出小易最少需要跳跃的步数,如果不能到达输出-1

输入例子:

4 24

输出例子:

5

ac注意

主要是再求约数的时候需要采用sqrt(n)的事件复杂度

本题是个简单的动态规划

#include <cstdio>#include <memory>#include <cassert>#include <cstdlib>#include <cmath>#include <cstring>#include <iostream>#include <string>#include <vector>#include <queue>#include <algorithm>#include <sstream>#include <stack> #include <map> #include <set> #include <unordered_map>using namespace std;const int INF = 0x7fffffff;const int MIN_INF = - INF -1;typedef long long int LL;int n , m;/* sqrt(n)的时间复杂度求约数(不包括 1 和 自身)*/vector<int> findyueshu(int n){    vector<int> ans;    int i;    for(i = 2; i*i <= n; i++)    {        if(n % i == 0)        {            int iv = n / i;            if(iv != i)            {                ans.push_back(i);                ans.push_back(iv);            }else{                ans.push_back(i);            }        }    }    return ans;}int main(){    //freopen("in.txt", "r", stdin);    vector<int> v = findyueshu(100);    while(scanf("%d%d", &n, &m) != EOF)    {        vector<int> v(m + 1, INF);        v[n] = 0;        for(int i=n;i<=m;i++)        {            if(v[i] == INF)                continue;            vector<int> yueshu = findyueshu(i);            int len = yueshu.size();            for(int j = 0; j < len; j++)            {                if(i + yueshu[j] <= m)                    v[i + yueshu[j]] = min(v[i + yueshu[j]], v[i] + 1);            }        }        if(v[m] == INF)            printf("-1\n");        else            cout << v[m] << endl;    }    return 0;}
0 0
原创粉丝点击