Codeforces Educational Round #18(Codeforces 792 A B C D)

5 篇文章 0 订阅

Codeforces Educational Round 18

想到再补。


CodeForces 792A New Bus Route

题意

给你一堆一维的坐标x,问你最近的两点距离以及这样最近距离的点对数。保证输入无重点。

思路

无重点就很简单了,排个序,扫一遍统计就行。

代码

#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <string>
#include <cstring>
#include <vector>
#include <cmath>
#include <queue>
#include <stack>
#include <map>

#define _ ios_base::sync_with_stdio(0),cin.tie(0)
#define M(a,b) memset(a,b,sizeof(a))
using namespace std;

const int MAXN=200007;
const int oo=0x3f3f3f3f;
typedef long long LL;
const LL loo=4223372036854775807ll;
typedef long double LB;
const LL mod=1e9+7;
LL dis[MAXN];
LL dd[MAXN];
int main()
{
    _;
    int n;
    while(cin>>n)
    {
        M(dis, 0);M(dd, 0);
        for(int i=0;i<n;i++)
        {
            cin>>dis[i];
        }
        sort(dis, dis+n);
        LL mindis=loo, minam=0;
        for(int i=1;i<n;i++)
        {
            LL tt=dis[i]-dis[i-1];
            if(tt<mindis)
            {
                mindis=tt;
                minam=1;
            }
            else if(tt==mindis) { minam++; }

        }
        cout<<mindis<<' '<<minam<<endl;

    }
    return 0;
}

CodeForces 792B Counting-out Rhyme

题意

猴子选大王。详细规则有点不同,每次数c[i]个人。

思路

直接模拟。我没模拟链表,就是加了个flag判断是否跳过这个人。
有一点注意,虽然每次的C[i]可能很大,但是最多只有100个人,每次模一下当前人数,然后一个个数也不会T。

代码

#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <string>
#include <cstring>
#include <vector>
#include <cmath>
#include <queue>
#include <stack>
#include <map>

#define _ ios_base::sync_with_stdio(0),cin.tie(0)
#define M(a,b) memset(a,b,sizeof(a))
using namespace std;

const int MAXN=107;
const int oo=0x3f3f3f3f;
typedef long long LL;
const LL loo=4223372036854775807ll;
typedef long double LB;
const LL mod=1e9+7;

int a[MAXN];
bool f[MAXN];
int co[MAXN];

int main()
{
    _;
    int n;
    while(cin>>n)
    {
        int m;cin>>m;
        M(a, 0);M(f, 0);M(co, 0);
        for(int i=0;i<m;i++)
        {
            cin>>co[i];
        }
        int leader=1;
        for(int i=0;i<m;i++)
        {
            co[i]=co[i]%(n-i);
            for(int j=0;j<co[i];j++)
            {
                do
                {
                    leader++;
                    if(leader>n) leader=1;
                } while(f[leader]==1);
            }

            cout<<leader<<(i==m-1 ? '\n' : ' ');
            f[leader]=1;
            do
            {
                leader++;
                if(leader>n) leader=1;
            } while(f[leader]==1);
        }
    }
    return 0;
}

CodeForces 792C Divide by Three

题意

给你一个数,位数在100000。让你删掉最少的数字,使得新的数能被3整除且没有前导0。

思路

一开始以为是dp。。就没做。。

其实被三整除,要求和被3整除。但是,被3除只可能余1或2。

所以从后往前记录一下被3除余1和2的数字的位置,各记录2个。然后在删。比如原数余1,那么可以删1个1或者2个2,比一下得到的结果(去掉前导零)谁长就行了。

为什么这么麻烦呢,因为有一种样例:2000000111。这个样例余2,但如果删2,会导致删的数太多,因为会删前导0。所以这题写起来很烦。。。各种情况。。所以被hack的多是这题。。。

代码

#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <string>
#include <cstring>
#include <vector>
#include <cmath>
#include <queue>
#include <stack>
#include <map>

#define _ ios_base::sync_with_stdio(0),cin.tie(0)
#define M(a,b) memset(a,b,sizeof(a))
using namespace std;

const int MAXN=107;
const int oo=0x3f3f3f3f;
typedef long long LL;
const LL loo=4223372036854775807ll;
typedef long double LB;
const LL mod=1e9+7;


int main()
{
    _;
    string s;
    while(cin>>s)
    {
        int k=0;
        while(s[k]=='0') k++;
        string ss=s.substr(k, s.size()-k);

        int n=ss.size();
        int sum=0;
        for(int i=0;i<n;i++)
        {
            sum+=ss[i]-'0';
        }

        if(sum%3==0)
        {
            cout<<ss<<endl;
        }
        else
        {
            int kk=sum%3;
            int p11=-1, p12=-1, p21=-1, p22=-1;
            for(int i=n-1;i>=0;i--)
            {
                if((ss[i]-'0')%3==1)
                {
                    if(p11==-1) p11=i;
                    else if(p12==-1) p12=i;
                }
                else if((ss[i]-'0')%3==2)
                {
                    if(p21==-1) p21=i;
                    else if(p22==-1) p22=i;
                }
            }
            bool flag=0;
            string ra=ss;
            string rb=ss;
            if(kk==1)
            {
                if(p11==-1&&p22==-1)
                {
                    flag=1;
                }
                if(p11!=-1)
                {
                    ra.erase(p11,1);
                    k=0;
                    while(ra[k]=='0') k++;
                    if(k==ra.size()&&k!=0) k--;
                    ra=ra.substr(k, ra.size()-k);
                }
                else ra="";

                if(p22!=-1)
                {
                    rb.erase(p21, 1);
                    rb.erase(p22, 1);
                    k=0;
                    while(rb[k]=='0') k++;
                    if(k==rb.size()&&k!=0) k--;
                    rb=rb.substr(k, rb.size()-k);
                }
                else rb="";
            }

            else if(kk==2)
            {
                if(p21==-1&&p12==-1)
                {
                    flag=1;
                }
                if(p21!=-1)
                {
                    ra.erase(p21, 1);
                    k=0;
                    while(ra[k]=='0') k++;
                    if(k==ra.size()&&k!=0) k--;
                    ra=ra.substr(k, ra.size()-k);

                }
                else ra="";

                if(p12!=-1)
                {
                    rb.erase(p11, 1);
                    rb.erase(p12, 1);
                    k=0;
                    while(rb[k]=='0') k++;
                    if(k==rb.size()&&k!=0) k--;
                    rb=rb.substr(k, rb.size()-k);
                }
                else rb="";
            }

            if(flag!=0||(ra.size()==0&&rb.size()==0)) cout<<-1<<endl;
            else
            {
                cout<<(ra.size()>rb.size() ? ra : rb)<<endl;
            }
        }
    }

    return 0;
}

CodeForces 792D Paths in a Complete Binary Tree

题意

给你一颗完全二叉搜索树,就是有 2n1 个节点那种的,编号从1开始。然后给一个起点,给一条路径(左儿子右儿子父亲),问你终点是多少。注意如果到某一步没法走,那么忽略当前字符。

思路

观察每一层,比如根节点是k,那么第一层(根节点层)可以正好整除k,下一层只能整除k/2,下一层k/4。。。

所以到某一个节点t,算一下它最大能被多少整除。假设为p。如果求父亲,那么他的父亲一定是t+p与t-p中能被2p整除却不能被4p整除的。
要是求儿子,左儿子是t-p/2,右儿子是t+p/2。

根节点没父亲,叶节点(只能被1整除)没儿子。
说起来比较绕,举个例子就好了。

代码

#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <string>
#include <cstring>
#include <vector>
#include <cmath>
#include <queue>
#include <stack>
#include <map>

#define _ ios_base::sync_with_stdio(0),cin.tie(0)
#define M(a,b) memset(a,b,sizeof(a))
using namespace std;

const int MAXN=107;
const int oo=0x3f3f3f3f;
typedef long long LL;
const LL loo=4223372036854775807ll;
typedef long double LB;
const LL mod=1e9+7;


int main()
{
    _;
    LL n;
    while(cin>>n)
    {
        int root=(n+1)>>1;
        int m;cin>>m;
        while(m--)
        {
            LL k;string s;
            cin>>k>>s;
            LL cur=k;
            for(int i=0;i<s.size();i++)
            {
                if(s[i]=='U')
                {
                    if(cur==root) continue;
                    LL now=1;
                    while(cur%now==0)
                    {
                        now*=2;
                    }
                    LL a=cur+(now/2), b=cur-(now/2);
                    if((a/now)%2!=0) cur=a;
                    else cur=b;
                }
                else if(s[i]=='L')
                {
                    if(cur%2==1) continue;
                    LL now=1;
                    while(cur%now==0)
                    {
                        now*=2;
                    }
                    cur=cur-(now/2/2);
                }
                else
                {
                    if(cur%2==1) continue;
                    LL now=1;
                    while(cur%now==0)
                    {
                        now*=2;
                    }
                    cur=cur+(now/2/2);
                }

            }
            cout<<cur<<endl;
        }
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值