Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/146.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ C+中的分治算法+;_C++_Algorithm_Divide And Conquer - Fatal编程技术网

C++ C+中的分治算法+;

C++ C+中的分治算法+;,c++,algorithm,divide-and-conquer,C++,Algorithm,Divide And Conquer,在一些在线法官身上有一个问题,我不知道如何被接受 问题是第一行包含两个数字 N (0 < N < 2^18) M (0 < M < 2^20) 问题是有多少X满足以下条件: M = floor(X/a1) + floor(X/a2) + ... + floor(X/an) 我天真的解决方案: #include<bits/stdc++.h> using namespace std; long long n,m,i,j,haha,sum; int main

在一些在线法官身上有一个问题,我不知道如何被接受

问题是第一行包含两个数字

N (0 < N < 2^18) 
M (0 < M < 2^20)
问题是有多少
X
满足以下条件:

M = floor(X/a1) + floor(X/a2) + ... + floor(X/an)
我天真的解决方案:

#include<bits/stdc++.h>
using namespace std;

long long n,m,i,j,haha,sum;
int main()
{
    cin >> n >> m;
    haha = 0;
    long long ar[n+5];
    for(i = 0; i < n; i++) cin >> ar[i];
    sort(ar,ar+n);
    for(i = ar[0]+1; i < m*ar[0]; i++){
        sum = 0;
        for (j = 0; j < n; j++) sum += i/ar[j];
        if (sum == m) haha += 1;
        else if (sum >= m) break;
    }
    cout << haha << endl;
}
#包括
使用名称空间std;
龙龙n,m,i,j,哈哈,和;
int main()
{
cin>>n>>m;
哈哈=0;
长ar[n+5];
对于(i=0;i>ar[i];
排序(ar,ar+n);
对于(i=ar[0]+1;i=m)中断,则为else;
}

无法更新

使用二进制搜索方法,下面是我的新代码:

// compute X/ai sum
long long summarize(long long ar[], long long n, long long X)
{
    long long sum = 0;
    for (long long i = 0; i < n; i++)
    {
        sum += X/ar[i];
    }
    return sum;
}

bool get_range(long long ar[], int n, int m, pair<long long, long long>& range)
{
    long long sum = 0;
    long long x;
    // reduce range
    while (range.first < range.second)
    {
        x = (range.first + range.second) / 2;

        sum = summarize(ar, n, x);
        if (sum < m)
        {
            range.first = x + 1;
        }
        else if (sum > m)
        {
            range.second = x;
        }
        else if (x == range.first)
        {
            return true; // single element
        }
        else
        {
            break;
        }
    }

    if (sum != m)
    {
        return false;
    }

    // check surroundings for lower / upper bound.
    sum = summarize(ar, n, range.first);
    if (sum != m)
    {
        auto r1 = make_pair(range.first + 1, x);
        if (get_range(ar, n, m, r1))
        {
            range.first = r1.first;
        }
        else
        {
            range.first = x;
        }
    }
    sum = summarize(ar, n, range.second - 1);
    if (sum != m)
    {
        auto r2 = make_pair(x + 1, range.second - 1);
        if (get_range(ar, n, m, r2))
        {
            range.second = r2.second;
        }
        else
        {
            range.second = x + 1;
        }
    }

    return true;
}


int main()
{
    int n, m;
    cin >> n >> m;
    long long *ar = new long long[n];
    long long ar_min = LLONG_MAX;
    for(long long i = 0; i < n; i++)
    {
        cin >> ar[i];
        ar_min = min(ar[i], ar_min);
    }
    // initial range of possible X values
    auto range = make_pair(m / (ar_min * n), m * ar_min);
    if (get_range(ar, n, m, range))
    {
        cout << (range.second - range.first) << endl;
    }
    else
    {
        cout << 0 << endl;
    }
}
对于每个子项
floor(X/a1)
,都有
floor(X1/ai)n>>m;
long-long*ar=新的long-long[n];
long long ar_最小值=long_最大值;
for(长i=0;i>ar[i];
ar_min=min(ar[i],ar_min);
}
//最低可能k
长k=m/(ar_min*n);
//获取可能的X值范围的值k
对于(;km)
{
打破
}
}
长X_min=k*ar_min,X_max=(k+1)*ar_min;
长结果=0;
//计算可能的X值
用于(长x=x_最小值;xm)
{
打破
}
}

cout我相信这个问题的预期解决方案是二进制搜索

定义
f(x)=sum\u i f(x/a\u i)
。在不丧失一般性的情况下,假设
a_i
以递增顺序给出

显然,

  • f(0)=0
  • f(M*a_1)≥ M
  • f(x)≥ f(y)如果x≥y
因此,您可以执行二进制搜索以查找x的最低值,从而
f(x)=M
,并将
start=0
end=M*a_1
作为二进制搜索的初始限制

要找到x的上限,请执行另一个二进制搜索,或只是循环遍历数组中的所有值,以找到最小的
y
,这样
floor(y/ai)>floor(x/ai)
对于某些
i

使用两个二进制搜索(分别用于下界和上界)和此代码(最终)被接受:

#include<bits/stdc++.h>
using namespace std;

long long n,m,i,l,r,mid1,mid2,ans,tmp,cnt,haha,k;
long long ar[26214400];
long long func(long long x){
    haha = 0;
    for (k = 0; k < n; k++) haha += x/ar[k];
    return haha;
}

int main()
{
    cin >> n >> m;
    for(i = 0; i < n; i++) cin >> ar[i];
    sort(ar,ar+n);
    l = ar[0];
    r = ar[0]*m;
    mid1 = (l+r)/2;
    tmp = func(mid1);
    while (l < r){
        mid1 = (l+r)/2;
        tmp = func(mid1);
        if (tmp < m) l = mid1+1;
        else if (tmp > m) r = mid1-1;
        else r = mid1-1;
    }
    mid1 = l; //lower bound
    l = ar[0];
    r = ar[0]*m;
    mid2 = (l+r)/2;
    tmp = func(mid2);
    while (l < r){
        mid2 = (l+r)/2;
        tmp = func(mid2);
        if (tmp < m) l = mid2+1;
        else if (tmp > m) r = mid2-1;
        else l = mid2+1;
    }
    mid2 = r; //upper bound
    while (mid1 <= mid2 and func(mid1) != m) mid1 += 1;
    while (mid2 >= mid1 and func(mid2) != m) mid2 -= 1;
    ans = mid2-mid1+1;
    cout << ans << endl;
}
#包括
使用名称空间std;
长长n,m,i,l,r,mid1,mid2,ans,tmp,cnt,哈哈,k;
long-long ar[26214400];
长函数(长x){
哈哈=0;
对于(k=0;k>n>>m;
对于(i=0;i>ar[i];
排序(ar,ar+n);
l=ar[0];
r=ar[0]*m;
mid1=(l+r)/2;
tmp=func(mid1);
while(lm)r=mid1-1;
否则r=mid1-1;
}
mid1=l;//下限
l=ar[0];
r=ar[0]*m;
mid2=(l+r)/2;
tmp=func(mid2);
while(lm)r=mid2-1;
否则l=mid2+1;
}
mid2=r;//上界
而(mid1=mid1和func(mid2)!=m)mid2-=1;
ans=mid2-mid1+1;

你能提供问题链接吗?@User\u Targaryen这个问题是用我的母语写的,来自当地的在线法官。证明这个链接不会有帮助。如果你真的想知道的话。@Aldihilman如果问题应该由D&C解决,我想这里唯一的选择是使用二进制搜索。谓词是“X使这个表达式等于M吗?",如果否,则沿已排序的X值向左或向右移动,如果是,则停止并检查X@grek40不起作用。例如,
N
=3和
M
=10。我们得到了
a1
=1、
a2
=1和
a3
=1。我们不可能得到
X
。然后展示您在二进制搜索方面的尝试。I讨论线性搜索毫无意义。不错的算法。但是你的算法比我最新的使用二进制搜索的算法慢。是的,你的算法也没有通过时间限制,它甚至得到了更低的分数。是的,后来我突然想到了“除法与合并”这个标题是密钥…正在进行更新,但尚未完成。是的。您的二进制搜索算法的分数与我的二进制搜索版本代码的分数相同。而且,您猜,它没有超过时间限制。@Aldihilman您是否有任何时间关键的示例测试用例或所有测试都是黑盒?很遗憾,黑盒。请共享您的二进制搜索代码,pe可以改进的rhaps。问题不在于二进制搜索,而在于二进制搜索后的while循环。这需要花费太长的时间。您应该使用二进制搜索来查找mid的最低值,而不是在第一个实例中中断。并使用另一个二进制搜索来查找第一个值,其中提供了更大的func。
// compute X/ai sum
long long summarize(long long ar[], long long n, long long X)
{
    long long sum = 0;
    for (long long i = 0; i < n; i++)
    {
        sum += X/ar[i];
    }
    return sum;
}

bool get_range(long long ar[], int n, int m, pair<long long, long long>& range)
{
    long long sum = 0;
    long long x;
    // reduce range
    while (range.first < range.second)
    {
        x = (range.first + range.second) / 2;

        sum = summarize(ar, n, x);
        if (sum < m)
        {
            range.first = x + 1;
        }
        else if (sum > m)
        {
            range.second = x;
        }
        else if (x == range.first)
        {
            return true; // single element
        }
        else
        {
            break;
        }
    }

    if (sum != m)
    {
        return false;
    }

    // check surroundings for lower / upper bound.
    sum = summarize(ar, n, range.first);
    if (sum != m)
    {
        auto r1 = make_pair(range.first + 1, x);
        if (get_range(ar, n, m, r1))
        {
            range.first = r1.first;
        }
        else
        {
            range.first = x;
        }
    }
    sum = summarize(ar, n, range.second - 1);
    if (sum != m)
    {
        auto r2 = make_pair(x + 1, range.second - 1);
        if (get_range(ar, n, m, r2))
        {
            range.second = r2.second;
        }
        else
        {
            range.second = x + 1;
        }
    }

    return true;
}


int main()
{
    int n, m;
    cin >> n >> m;
    long long *ar = new long long[n];
    long long ar_min = LLONG_MAX;
    for(long long i = 0; i < n; i++)
    {
        cin >> ar[i];
        ar_min = min(ar[i], ar_min);
    }
    // initial range of possible X values
    auto range = make_pair(m / (ar_min * n), m * ar_min);
    if (get_range(ar, n, m, range))
    {
        cout << (range.second - range.first) << endl;
    }
    else
    {
        cout << 0 << endl;
    }
}
M = floor(X/a1) + floor(X/a2) + ... + floor(X/an)
// compute X/ai sum
long long summarize(long long ar[], long long n, long long X)
{
    long long sum = 0;
    for (long long i = 0; i < n; i++)
    {
        sum += X/ar[i];
    }
    return sum;
}

int main()
{
    int n, m;
    cin >> n >> m;
    long long *ar = new long long[n];
    long long ar_min = LLONG_MAX;
    for(long long i = 0; i < n; i++)
    {
        cin >> ar[i];
        ar_min = min(ar[i], ar_min);
    }

    // lowest possible k
    long long k = m / (ar_min * n);
    // get the value k for a possible range of X values
    for (; k <= m; k++)
    {
        auto x = ar_min * (k + 1);
        long long sum = summarize(ar, n, x);
        if (sum > m)
        {
            break;
        }
    }
    long long X_min = k * ar_min, X_max = (k + 1) * ar_min;
    long long result = 0;
    // count possible X values
    for (long long x = X_min; x < X_max; x++)
    {
        long long sum = summarize(ar, n, x);
        if (sum == m)
        {
            ++result;
        }
        else if (sum > m)
        {
            break;
        }
    }

    cout << result << endl;
}
#include<bits/stdc++.h>
using namespace std;

long long n,m,i,l,r,mid1,mid2,ans,tmp,cnt,haha,k;
long long ar[26214400];
long long func(long long x){
    haha = 0;
    for (k = 0; k < n; k++) haha += x/ar[k];
    return haha;
}

int main()
{
    cin >> n >> m;
    for(i = 0; i < n; i++) cin >> ar[i];
    sort(ar,ar+n);
    l = ar[0];
    r = ar[0]*m;
    mid1 = (l+r)/2;
    tmp = func(mid1);
    while (l < r){
        mid1 = (l+r)/2;
        tmp = func(mid1);
        if (tmp < m) l = mid1+1;
        else if (tmp > m) r = mid1-1;
        else r = mid1-1;
    }
    mid1 = l; //lower bound
    l = ar[0];
    r = ar[0]*m;
    mid2 = (l+r)/2;
    tmp = func(mid2);
    while (l < r){
        mid2 = (l+r)/2;
        tmp = func(mid2);
        if (tmp < m) l = mid2+1;
        else if (tmp > m) r = mid2-1;
        else l = mid2+1;
    }
    mid2 = r; //upper bound
    while (mid1 <= mid2 and func(mid1) != m) mid1 += 1;
    while (mid2 >= mid1 and func(mid2) != m) mid2 -= 1;
    ans = mid2-mid1+1;
    cout << ans << endl;
}