[Algorithms]Constructive Algorithm构造算法

构造算法是什么

It's an algorithm which builds something. A graph, an array, a matrix etc. It's what test generators use to build test cases.

就是数学中的proof,

         constrcutive proof:具体地给出某一对象或者能给出某一对象的计算方法

         Non-constructive proof :证明的过程中,不举例而只证明语句是否正确。通常使用反正法

 

Example:             

                                                                                                CF1157D N Problems During K Days
Polycarp has to solve exactly n problems to improve his programming skill before an important programming competition. But this competition will be held very soon, most precisely, it will start in k days. It means that Polycarp has exactly k days for training!
Polycarp doesn't want to procrastinate, so he wants to solve at least one problem during each of k days. He also doesn't want to overwork, so if he solves x problems during some day, he should solve no more than 2x problems during the next day. And, at last, he wants to improve his skill, so if he solves x problems during some day, he should solve at least x+1 problem during the next day.

More formally: let [a1,a2,…,ak] be the array of numbers of problems solved by Polycarp. The i-th element of this array is the number of problems Polycarp solves during the i-th day of his training. Then the following conditions must be satisfied:

sum of all ai for i from 1 to k should be n;
ai should be greater than zero for each i from 1 to k;
the condition ai<ai+1≤2ai should be satisfied for each i from 1 to k−1.
Your problem is to find any array a of length k satisfying the conditions above or say that it is impossible to do it.

Input
The first line of the input contains two integers n and k (1≤n≤109,1≤k≤105) — the number of problems Polycarp wants to solve and the number of days Polycarp wants to train.

Output
If it is impossible to find any array a of length k satisfying Polycarp's rules of training, print "NO" in the first line.

Otherwise print "YES" in the first line, then print k integers a1,a2,…,ak in the second line, where ai should be the number of problems Polycarp should solve during the i-th day. If there are multiple answers, you can print any.

 题意:

构造一个数列an,使∑an= n,1<=i <=k,0<ai<ai+1≤2ai

分析:

该数列在有上下界约束条件下单调递增,

下界:公差为1的等差数列求和

上界:公比为2的等比数列求和

对每个ai,,,ak的子数列首项(即当前ai)采取greedy,取当前上下界约束条件下的最大值(使当前子数列达到最优解,尽可能多)。

注:求满足上界约束的ai时要上取整,下取整会达不到上界

排除情况:

不满足下界约束:子数列之和下界大于当前n

#include<iostream>
#include<cmath>
using namespace std;
long long a[110000];
long long sum(long long m)
{
    return m*(m+1)/2;
}
int main()
{
    int n,k;
    cin>>n>>k;
    for(int i=1;i<=k;i++)
    {
        long long ans=max((int)(a[i-1]+1),(int)ceil((double)n/(double)(pow(2.0,k+1-i)-1)));//约束条件下的greedy
        if(sum(ans-i+k)-sum(ans-1)>n)//下界约束情况排除
        {
            cout<<"NO"<<endl;
            return 0;
        }
        a[i]=ans;
        n-=ans;//更新当前n
    }
    cout<<"YES"<<endl;
    for(int i=1;i<=k;i++)
    {
        cout<<a[i]<<" ";
    }
    return 0;
}

 

猜你喜欢

转载自www.cnblogs.com/HuisClos/p/10831914.html