Help is needed for Dexter UVA - 11384(分治 找规律)

题目描述:给定一串数字1~n,每次可以选取任意个数字对他们减去任意一个数字x,求将这n个数全部减为0所需的最小处理次数。

思路:我做时算是在边推边找规律吧,推到n为12才突然反应过来:F(n) = F(n / 2) + 1。如1 2 3 4 5 6 7首先将4 5 6 7分别减去4得到1 2 3 0 1 2 3此时相当于将原来的串1 2 3 4 5 6 7 变成了1 2 3,然后将所有的2 3减去2,得到1 0 1 0 1 0 1,最后再将所有的1减去1得到0 0 0 0 0 0 0。原本想用数组保存结果直接输出的,结果发现n最大为1e9,数组开不下,又想了想其实就是分治递归的思想每次给定一个n直接递归求解即可。不过为了节约时间,还是用数组储存了部分结果,其实是没有必要的。直接递归求解时间为30ms,而开数组是340ms,反而更耗时。

代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#include<cstdlib>
#include<sstream>
#include<deque>
#include<stack>
#include<set>
#include<map>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const double eps = 1e-6;
const int maxn = 2 * 1e8 + 10;
const int maxt = 1e6 + 10;
const int mod = 10000007;
const int dx[] = {1, -1, 0, 0, -1, -1, 1, 1};
const int dy[] = {0, 0, -1, 1, -1, 1, -1, 1};
const int Dis[] = {-1, 1, -5, 5};
const double inf = 0x3f3f3f3f;
ll num[maxn];
int  n, m, k;
ll solve(int n){
    if(n == 1) return 1;
    return solve(n / 2) + 1;
}
int main(){
    while(scanf("%d", &n) != EOF){
        ll ans = solve(n);
        printf("%lld\n", ans);
    }
    return 0;
}
下面这段代码,原本想节省时间的,结果反而是多此一举了,更耗时。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#include<cstdlib>
#include<sstream>
#include<deque>
#include<stack>
#include<set>
#include<map>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const double eps = 1e-6;
const int maxn = 2 * 1e8 + 10;
const int maxt = 1e6 + 10;
const int mod = 10000007;
const int dx[] = {1, -1, 0, 0, -1, -1, 1, 1};
const int dy[] = {0, 0, -1, 1, -1, 1, -1, 1};
const int Dis[] = {-1, 1, -5, 5};
const double inf = 0x3f3f3f3f;
ll num[maxn];
int  n, m, k;
void init(){
    num[0] = 0;
    num[1] = 1;
    num[2] = 2;
    for(int i = 3; i < maxn; ++i){
        num[i] = num[i / 2] + 1;
    }
}
ll solve(int n){
    if(n < maxn) return num[n];
    return solve(n / 2) + 1;
}
int main(){
    init();
    while(scanf("%d", &n) != EOF){
        if(n < maxn)printf("%lld\n", num[n]);
        else{
            ll ans = solve(n);
            printf("%lld\n", ans);
        }
    }
    return 0;
}





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值