比赛的时候没做出C来,是个简单的二分,有点可惜。后来用二分法做了一下也做出来了,感觉是能力范围之内的题…
A. Distance
有A.B.C三个坐标点,A为(0,0),给出B的坐标点,要求满足两个式子:
d(A,C)=d(A,B)/2 d(B,C)=d(A,B)/2 如果能找到C就输出任意一个满足答案的坐标,如果不能找到则输出-1。
在编程中除特殊情况外尽量不要出现除法,随时可能会导致错误。把2挪到式子左边比较好,坐标的范围也很小,直接遍历查找就可以了。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int main()
{
int i,n,t,ans=0,j,x,y,u,w,o,p;
cin>>t;
while(t--)
{ p=0;
cin>>x>>y;
for(i=0;i<=50;i++)
{
for(j=0;j<=50;j++)
{
u=x-0+y-0;
w=abs(i-0)+abs(j-0);
o=abs(i-x)+abs(j-y);
if(u==2*w&&u==2*o) {p=1;break;}
}
if(p==1) break;
}
if(p==1) cout<<i<<" "<<j<<endl;
else cout<<"-1"<<" "<<"-1"<<endl;
}
}
B. Special Permutation
设定序列为1-n,给出序列长度(偶数),将序列平分为左右两半,给出左半序列最小值a,右半序列最大值b,判断是否有这样的序列,如果没有则输出-1,有则任意输出一个满足答案的序列。
首先要判断是否存在这样的序列,给出a,所以要把左边剩下的部分全部填上比a大的数,但是a可能比较大使得左边a并不是最小值,这样就不会有这个序列,右边同理。满足a为最小值b为最大值后从大到小往左、右两个序列里赋值,最后输出序列即可。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int main()
{
int i,n,t,a,b,sum,num;
cin>>t;
while(t--)
{ sum=0;num=0;
cin>>n>>a>>b;
int p=n;
int c[n];
int aver=n/2;
for(i=1;i<=n;i++)
{
if(i>a) sum++;
}
for(i=1;i<=n;i++)
{
if(i>b) num++;
}
if(a>b) num--;
if(a<b) sum--; // 个人的判断序列是否成立的方法,有些复杂,肯定大佬写的要简单点
if(sum<aver-1||num>aver-1) {cout<<"-1"<<endl;continue;}
else {
c[0]=a;
for(i=1;i<aver;i++)
{
while(p==b||p==a)
{p--;}
c[i]=p;
p--;
}
c[aver]=b;
for(i=aver+1;i<n;i++)
{
while(p==a||p==b) {p--;}
c[i]=p;
p--;
}
for(i=0;i<n;i++)
{
cout<<c[i]<<" ";
}
cout<<endl;
}
}
}
C. Chat Ban
以上为发送三条消息产生的图形,k为3,总数为9
现在一个人想要发送消息,但是发送过多条的图形会被管理员限制,给出k和限制数x(一个图形算一个,不能发送比x还多的图形),求它最多能发送多少条消息(一行算一条,哪怕这行只发送出一个图形,也算发送出了这条消息),求这个人最多能发送出多少条消息。
听说可以用纯数学,但我看到可以用二分来做立马感觉可以试试。首先可以将大图分为两个等差数列,等差数列求和的公式不用说了吧。接下来就是查找这个和的位置了,这简直就是直接套二分模板,我把两个等差数列分情况列了两个二分,好像大佬用一个二分就行了。
因为ans开的不够大,还是导致我wr了几次。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int main(){
ll t,l,r,mid;
cin>>t;
while(t--){
ll ans=10000000000;
ll k,x;
cin>>k>>x;
if(x>=k*k) {cout<<2*k-1<<endl;continue;}
l=1;r=k;
while(l<=r)
{ // 我们要查找刚好被管理员限制的位置发送了几条消息
mid=(l+r)/2;
if(mid*(mid+1)/2>=x)
{ // 只要消息总数比限制数大就要减少消息的条数
r=mid-1;
ans=min(ans,mid);
}
else l=mid+1; // 消息总数比限制数小我们就可以增加消息的条数
}
if(x<=k*(k+1)/2){
cout<<ans<<endl;
continue;
}
if(x>k*(k+1)/2&&x<k*k)
{
x=x-k*(k+1)/2;
l=1;r=k-1;
ans=10000000000;
while(l<=r)
{
mid=(l+r)/2;
if(mid*(2*k-1-mid)/2>=x)
{
r=mid-1;
ans=min(ans,mid);
}
else l=mid+1;
}
cout<<ans+k<<endl;
continue;
}
}
return 0;
}