题目大意:
求出中,k从1到n的所有解,注意相同的不需要打印。n=1e9.
解题思路:
首先我们可以暴力枚举k打表找找规律。然后我们发现,首先这个函数是单调递减的。同时,因为我们需要输出答案,所以答案数量不会太多。我们考虑这样子做二分,每次我们从x到n做二分。x为相同中的最小的k。然后我们找到它的右边界到哪里。
什么意思呢?
若n=108,通过暴力k我们得到如下的.
108 54 36 27 21 18 15 13 12 10 9 9 8 7 7 6 6 6 5 5 5 4 4 4 4 4 4 3 3 3 3 3 3 3 3 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
第一次x为1,它只有一个数,所以下次x+1作为起点,一直到x=11的位置,对应的 =9,那么我们通过二分得到下一个起点为13.
#include <bits/stdc++.h>
using namespace std;
int main(){
int cas;cin>>cas;
while(cas--){
int n;cin>>n;
vector<int> ans;
int x,y;
x=1;y=n+1;
while(x<=n){
ans.push_back(n/x);
int val=n/x;
while(x<y){
int mid=x+(y-x)/2;
if(n/mid<val)y=mid;
else x=mid+1;
}
y=n+1;
}
ans.push_back(0);
reverse(ans.begin(),ans.end());
cout<<ans.size()<<endl;
for(auto it:ans)cout<<it<<" ";
cout<<endl;
}
return 0;
}