Codeforces 360B + Codeforces 689C ( 二分 + DP )

http://codeforces.com/contest/360/problem/B

B. Levko and Array

Levko has an array that consists of integers: a1, a2, … , an. But he doesn’t like this array at all.

Levko thinks that the beauty of the array a directly depends on value c(a), which can be calculated by the formula:
The less value c(a) is, the more beautiful the array is.

It’s time to change the world and Levko is going to change his array for the better. To be exact, Levko wants to change the values of at most k array elements (it is allowed to replace the values by any integers). Of course, the changes should make the array as beautiful as possible.

Help Levko and calculate what minimum number c(a) he can reach.
Input

The first line contains two integers n and k (1 ≤ k ≤ n ≤ 2000). The second line contains space-separated integers a1, a2, … , an ( - 109 ≤ ai ≤ 109).
Output

A single number — the minimum value of c(a) Levko can get.

Examples
Input

5 2
4 7 4 7 4

Output

0

Input

3 1
-100 0 100

Output

100

Input

6 3
1 2 3 7 8 9

Output

1

题意
最多改变数组中K个数,使这个数组满足:任意两个相邻的数的绝对值差的最大值最小。这种问题一般会想到二分,二分的L,R 为 0初始时绝对值差的最大值。 判断二分的时候 bool check(mid),这里用到dp思想。
bool check(mid)的主要功能是:若绝对值差的最大值为Mid,判断改变的数的个数与K的大小判断。 dp[i]表示不改变第i个数,前面的都符合情况所需要改变的个数。二重循环遍历之。很好的思想。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

typedef long long LL;
const int N = 2000 + 100;
LL arr[N], dp[N];
int n,k;

bool check(LL mid)
{
        for(int i=1;i<=n;i++)
        {
                dp[i] = i-1;
                for(int j=1;j<i;j++)
                {
                        if( abs(arr[i] - arr[j]) <= (i-j)*mid )
                                dp[i] = min(dp[i],dp[j] + (i-j-1));
                }
                if(dp[i] + n-i <= k) return true;
        }
        return false;
}
int main()
{
        scanf("%d%d",&n,&k);
        LL L = 0, R = 0;
        for(int i=1;i<=n;i++)
        {
                scanf("%I64d",&arr[i]);
                if(i!=1) R = max(R,abs(arr[i]-arr[i-1]));
        }
        while( L+1 <= R )
        {
                LL mid = (L + R) >> 1;
                if( check(mid) )  R = mid;
                else L = mid + 1;
        }
        printf("%I64d\n",R);
        return 0;
}

http://codeforces.com/problemset/problem/689/C

Mike and Chocolate Thieves

Bad news came to Mike’s village, some thieves stole a bunch of chocolates from the local factory! Horrible!

Aside from loving sweet things, thieves from this area are known to be very greedy. So after a thief takes his number of chocolates for himself, the next thief will take exactly k times more than the previous one. The value of k (k > 1) is a secret integer known only to them. It is also known that each thief’s bag can carry at most n chocolates (if they intend to take more, the deal is cancelled) and that there were exactly four thieves involved.

Sadly, only the thieves know the value of n, but rumours say that the numbers of ways they could have taken the chocolates (for a fixed n, but not fixed k) is m. Two ways are considered different if one of the thieves (they should be numbered in the order they take chocolates) took different number of chocolates in them.

Mike want to track the thieves down, so he wants to know what their bags are and value of n will help him in that. Please find the smallest possible value of n or tell him that the rumors are false and there is no such n.

Input

The single line of input contains the integer m (1 ≤ m ≤ 1015) — the number of ways the thieves might steal the chocolates, as rumours say.

Output

Print the only integer n — the maximum amount of chocolates that thieves’ bags can carry. If there are more than one n satisfying the rumors, print the smallest one.

If there is no such n for a false-rumoured m, print  - 1.
Examples
Input

1

Output

8

Input

8

Output

54

Input

10

Output

-1

题意:
给一个数字n,要求结果正好包含n个四元组,求这n个四元组里的最大值,四元组形式为一个等比数列。

因为只有四个数,显然最后一个是第一个的x^3倍,二分答案,枚举x计算四元组个数即可。

#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <math.h>
using namespace std;

long long get(long long n)
{
        long long res = 0;
        for(long long i=2; i*i*i <= n; i++)
                res += n/(i*i*i); 
        return res;
}
int main()
{
        long long n = -1,m; 
        scanf("%I64d",&m);

        long long l = 0 , r = 5 * 1e15;
        while( l<r )
        {
                long long mid = (long long)(l+r) >> 1;
                if(get(mid)>=m) r = mid;
                else l = mid+1;
        }
        if(get(l)==m)  n = l;
        printf("%I64d\n",n);
        return 0;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值