1 条题解
-
0
首先我们先构造一条直线上最多能放几个点。先将这条直线上的点的贡献算出来。
我们设直线上有 个点,那么产生的贡献就是 。并且由于 极大,剩余需要的贡献不超过 ,记为 。
那么我们就可以排列一下直线上的点的分布方式,新增一个点,使得其正好和直线上 个点距离为整数。
也就是说,对于这个新点,我们设他离直线的距离为 ,那么这个 必须至少和 个数构成勾股数的前两个。
这时候既可以打表也可以公式算出这个 。如果使用公式那么有:,我们从 下手。也就是说我们要让 有较多的因子。这里采用 作为 ,即 $2 \times 3 \times 5 \times 7 \times 11 \times 13 \times 17$。
接下来就要决定直线上每个点的位置。我们固定直线的 坐标为 ,固定新点坐标 。令直线上 个点的 坐标能和 构成勾股数的前两个,剩下的 个点则不能。最后还有 个点没有用上,这里直接全部流放到角落。
下附代码。
#include<iostream> #include<cstdio> #include<cmath> #define int long long #define PII pair<int,int> using namespace std; int n,k,dis=510510; bool check(int a,int b){//判断能否构成勾股数 int c=sqrt(a*a+b*b); if(c*c==a*a+b*b) return 1; return 0; } signed main(){ cin>>n>>k; if(k==n*(n-1)/2){ for(int i=1;i<=n;i++) cout<<"0 "<<i<<endl; return 0; } if(k==0){ for(int i=1;i<=n;i++) cout<<i<<' '<<i<<endl; return 0; } int len=1; while(len*(len+1)/2<=k-1) len++; int res=k-len*(len-1)/2;//res为需要的贡献 cout<<"0 "<<dis<<endl;//用来组成勾股数的新点 int x=1; for(int i=1;i<=res;i++){//寻找能组成勾股数的坐标 while(!check(x,dis)) x++; cout<<x<<' '<<0<<endl;x++; } for(int i=1;i<=len-res;i++){//剩下的点不能产生贡献 while(check(x,dis)) x++; cout<<x<<' '<<0<<endl;x++; } for(int i=len+2;i<=n;i++) cout<<1000000000-i<<' '<<-1000000000+i<<endl; return 0; }
- 1
信息
- ID
- 12556
- 时间
- 1000ms
- 内存
- 700MiB
- 难度
- 10
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者