F题解法各异,我分享一下我的解法吧。
采取贪心策略。第一个点肯定产生不了点对,我放在(0,0),接着
①如果分别向x方向和y方向拓展一个点。那么我们可以获得1个点对。
②如果把点放在(x,y),其中(x-1,y)和(x,y-1)都被点占据,那可以得到2个点对。这种情况要怎样才能满足呢?假设x,y方向拓展到的最大点分别是xm和ym,那么可以提供xm*ym次,放一个点增加2的机会。
x+y固定的情况下,x和y越接近,x*y越大。所以加到xm和ym的较小值上,这样能提供更多。
然后就贪心地一直添加点。要尽可能地多就得采取以上策略。如果k=1,那就采取操作1。否则能用操作2就用操作2。直到k等于0。
做完这些后,再看一下用了多少个点。如果点有剩,那就随便找个地方放。
using namespace std;
#include <bits/stdc++.h>
#define ll long long
#define PII pair<int,int>
int main(){
int n,k;
cin>>n>>k;
vector<PII>ans;
ans.push_back({0,0});
n--;
queue<PII>q;
int xm=0,ym=0;
while(k){
if(k==1||q.empty()){
if(ym<xm){
ans.push_back({0,++ym});k--;n--;
for(int i=1;i<=xm;i++)q.push({i,ym});
}
else{
ans.push_back({++xm,0});k--;n--;
for(int i=1;i<=ym;i++)q.push({xm,i});
}
}
else{
ans.push_back(q.front());q.pop();
k-=2;n--;
}
}
if(n<0){
cout<<"No"<<endl;return 0;
}
cout<<"Yes"<<endl;
for(auto [x,y]:ans)cout<<x<<' '<<y<<endl;
while(n--){
cout<<1919810<<' '<<n*2<<endl;
}
}

京公网安备 11010502036488号