Educational Codeforces Round 117 (Rated for Div. 2) A-C

比赛的时候没做出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;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值