【发布时间】:2017-06-08 20:11:41
【问题描述】:
网上某评委有这么一个问题,我不知道如何录取。
问题是这样的,第一行包含两个数字
N (0 < N < 2^18)
M (0 < M < 2^20)
第二行包含N 数字
ai (0 < ai < 2^40)
问题是有多少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;
}
更新1: 我的二分查找解决方案(仍然没有超过时限):
#include<bits/stdc++.h>
using namespace std;
long long n,m,i,l,r,mid,ans,tmp,cnt,haha;
long long ar[2621440];
long long func(long long x){
haha = 0;
for (i = 0; i < n; i++) haha += x/ar[i];
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;
mid = (l+r)/2;
tmp = func(mid);
while (tmp != m){
mid = (l+r)/2;
tmp = func(mid);
if (l == r) break;
if (tmp < m) l = mid+1;
else if (tmp > m) r = mid-1;
else break;
}
ans = 0;
if (tmp == m) ans += 1;
cnt = mid;
while (func(cnt-1) == m){
ans += 1;
cnt -= 1;
}
cnt = mid;
while (func(cnt+1) == m){
ans += 1;
cnt += 1;
}
cout << ans << endl;
}
【问题讨论】:
-
能否提供问题链接?
-
@User_Targaryen 这个问题是用我的母语写的,来自当地的在线评委。证明链接无济于事。如果你真的想知道link.
-
@Aldihilmanr 如果问题应该由 D&C 解决,我认为这里唯一的选择是使用二进制搜索。谓词是“X 是否使这个表达式等于 M?”,如果不是,那么你沿着排序的 X 值向左或向右,如果是,你停下来检查 X 的邻域
-
@grek40 不起作用。例如
N= 3 和M= 10。我们得到a1= 1、a2= 1 和a3= 1。我们没有X的可能性。 -
然后显示您对二分搜索的尝试。讨论线性搜索是没有意义的。
标签: c++ algorithm divide-and-conquer