Educational Codeforces Round 156 (Rated for Div. 2)

Educational Codeforces Round 156 (Rated for Div. 2)

A. Sum of Three

guess+数学 800

要找三个不同的数使得: x+y+z == n,并且每个数都无法被3整除

请问是否存在这样的三元组?

对于一个数,它模以3只有三种结果:0,1,2

如果这个数,被分成2个数a,b

那么a,b模以3也只有三种结果,0,1,2

现在我们要a,b模以3不等于0

所以我们直接让 a=2 b=n-2 那么判断一下 b>2 and b%3!=0 即可

或者 a=4 b=n-4 判断一下 b>4 and b%3!=0 即可

为什么取2和4? 因为2%3的余数是2,4%3的余数是1

#include<bits/stdc++.h>
using namespace std;

#define int long long
#define PII pair<int,int>
void slove(){
   int n;
   cin>>n;
   n--;
   
   if(n-2 > 2){
       int r1=(n-2)%3;
       if(r1!=0){
           cout<<"YES"<<endl;
           cout<<1<<' '<<2<<' '<<n-2<<endl;
           return;
       }
   }
   
    if(n-4>4 ){
       int r1=(n-4)%3;
       
       if(r1!=0){
           cout<<"YES"<<endl;
           cout<<1<<' '<<4<<' '<<n-4<<endl;
           return;
       }
       
   }
   
    cout<<"NO"<<endl;
}

signed main(){
    int t;
    cin>>t;
    while(t--){
        slove();
    }
}


B. Fear of the Dark

二分+分类讨论 1200

从(0,0)开始一共有4种情况能到达 ( P x , P y ) (P_x,P_y) (Px,Py)

0—> a—>p

0—>b---->p

0---->a---->b---->p

0---->b----->a----->p

然后二分半径就行了。

可以提前算出来 0----a、0-----b、a-----b、a----p、b-----p 之间的距离

然后简单check就行了,当满足上面任意条件,mid缩小

否则mid变大

#include<bits/stdc++.h>
using namespace std;

#define int long long
#define PII pair<int,int>
void slove(){
     PII p,a,b;
     cin>>p.first>>p.second>>a.first>>a.second>>b.first>>b.second;
     
     double lena= sqrt(pow(a.first,2)+pow(a.second,2));
     double lenb=sqrt(pow(b.first,2)+pow(b.second,2));
     double lenab=sqrt(pow(a.first-b.first,2)+pow(a.second-b.second,2));
     double inf=1e-6;
     double lenap=sqrt(pow(a.first-p.first,2)+pow(a.second-p.second,2));
     double lenbp=sqrt(pow(b.first-p.first,2)+pow(b.second-p.second,2));
     
     
     auto check=[&](double mid){
         // 第一种情况,0->a->b->p
         if(mid>=lena and 2*mid>=lenab and (mid>=lenbp or mid>=lenap)){
             return 1;
         }
         // 0->b->a->p
          if(mid>=lenb and 2*mid>=lenab and (mid>=lenbp or mid>=lenap) ){
             return 1;
         }
         
         // 0->a->p
          if(mid>=lena and mid>=lenap){
             return 1;
         }
         
         //0->b->p
          if(mid>=lenb and mid>=lenbp){
             return 1;
         }
         
          return 0;
        
     };
     
     double l=0,r=1e9;
     while(r-l>inf){
         double mid=(l+r)/2;
         if(check(mid))r=mid;
         else l=mid;
     }
     
     printf("%.10lf\n",l);
}

signed main(){
    int t;
    cin>>t;
    while(t--){
        slove();
    }
}


C. Decreasing String

字符串处理,贪心 1600

考虑一个问题: 对于一个字符串,我们只能删除一个字符,使得这个字符串的字典序最小。

我们应该怎么删除?

答案是,删除第一个逆序的字符即可。

暴力做法:

假如我们要获得第 k次的字符串,那么我们重复k次,每次将第一个遇到的逆序字符删除就行了。

对于我们要获得第几次的字符串,就需要从位置n入手,因为第0次的字符串,删除了0个字符,长度为s.size()

第k次的字符串,删除了k个字符,长度为s.size()-k

那么累加起来,你会发现是一个等差数列求和。

可以选择lower_bound查找前缀和,也可以不断减去s.size()-i

减到不能再减即可。

#include<bits/stdc++.h>
using namespace std;

#define int long long
#define PII pair<int,int>
void slove(){
    string s;
    cin>>s;
    int len=s.size();
    int pos;
    cin>>pos;
    int sum=0;
    int cnt=0; //记录pos在第几个字符串
    
    for(int i=1;i<=len;i++){
        sum+=(len-i+1);
        if(pos<=sum){
            cnt=i;
            sum-=(len-i+1);
            break;
        }
    }
    
    
    int yu=pos-sum; //在第cnt个字符串中的位置
  //  cout<<cnt<<endl;
    
    int bnt=1; //当前迭代到第几个字符串
    string t;
    for(int i=0;i<s.size();i++){
       t+=s[i];
       while(bnt<cnt and t.back()>s[i+1] and t.size() and i!=s.size()-1 ){
           t.pop_back();
           bnt++;
       }
       
    }

    cout<<t[yu-1];
}

signed main(){
    int t;
    cin>>t;
    while(t--){
        slove();
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

louisdlee.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值