2021-11-07

Codeforces Round #805 (Div. 3)

Problem - A

题意:

给你一个数,输出它和所在位数的10的次方的差值。

思路:

从1开始不停 × 10 \times10 ×10,直到大于这个数字的时候停止,判断这个本来的数是不是就是10的次方,是就输出0,不是就相减就行。

代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e5+10;
#define PI 3.14159265358979323846;
const int INF = 0x3f3f3f3f;

void solve()
{
    int n;
    cin>>n;
    int m=1;
    while(m<n)
        m*=10;
    if(m==n)
    cout<<0<<endl;
    else
    cout<<n-m/10<<endl;
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int Times;
    cin>>Times;
    while(Times--)
    solve();
    return 0;
}

Problem - B

题意:

给你一个由a~z组成字符串,告诉你你每次只能取三个字母,问多少次可以取完?

思路:

每次遇到不同的字母就用数组存下,假如不同的数组数量达到了四个,就将计数器归一,同时答案+1.不能够达到3个的时候就归0,因为达到3以后可能下几个还是由找到的三个字母组成。

代码

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e5+10;
#define PI 3.14159265358979323846;
const int INF = 0x3f3f3f3f;
bool a[26];
int b[3];
void solve()
{
    memset(a,0,sizeof(a));
    string s;
    cin>>s;
    int n=s.length();
    int t=0,ans=0;;
    for(int i=0;i<n;i++)
    {
        if(a[s[i]-'a']==0)
        {
            t++;
            a[s[i]-'a']=1;
        }
        if(t==4)
        {
            memset(a,0,sizeof(a));
            a[s[i]-'a']=1;
            t=1;
            ans++;
        }
    }
    if(t>0)
    ans++;
    cout<<ans<<endl;
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int Times;
    cin>>Times;
    while(Times--)
    solve();
    return 0;
}

Problem - C

题意:

给你一个序列,你只能从前往后走,给你q个询问,问你能不能从a数字走到b数字,改序列可能存在相同的数组。

思路:

用两个map来存这个数的最前和最后,假如a的最前还比b的最后往后,那注定无法走在一起。同时也要判断一下存不存在这个数,只要不存在就没有必要判断了。

代码

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 2e5+10;
#define PI 3.14159265358979323846;
const int INF = 0x3f3f3f3f;
int a[maxn];
map<int,int> st;
map<int,int> ed;
map<int,bool> mp;
void solve()
{
    mp.clear();
    st.clear();
    ed.clear();
    int n,t;
    cin>>n>>t;
    for(int i=0;i<n;i++)
    {
        cin>>a[i];
        if(mp.count(a[i])==0)
        {
            mp[a[i]]=1;
            st[a[i]]=i;
        }
        ed[a[i]]=i;
    }
    while(t--)
    {
        int l,r;
        cin>>l>>r;
        if(mp.count(l)==0||mp.count(r)==0)
        cout<<"NO"<<endl;
        else
        {
            if(st[l]<=ed[r])
            cout<<"YES"<<endl;
            else
            cout<<"NO"<<endl;
        }
    }
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int Times;
    cin>>Times;
    while(Times--)
    solve();
    return 0;
}

Problem - D

题意:

给你一个字符串, a a a的权值是1, b b b的权值是2,以此类推。给你一个sum,问你怎么删除这个字符串最少的个数才能使得这个字符串小于这个sum.

思路:

假如本来就是小于sum的,直接输出。假如大于的话用一个pair存它的值和位置,然后进行排序。从小到大开始加(从大到小的逆向思维),假如计数的这个num小于sum就继续加,直到大于sum.加的过程记录下位置,之后输出这些位置上的字符串。

代码

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 2e5+10;
#define PI 3.14159265358979323846;
const int INF = 0x3f3f3f3f;
pair<int,int> a[maxn];
bool b[maxn];
void solve()
{
    memset(b,0,sizeof(b));
    memset(a,0,sizeof(a));
    string s;
    int num;
    cin>>s>>num;
    int n=s.length();
    int sum1=0;
    for(int i=0;i<n;i++)
    sum1+=(s[i]-'a'+1);
    if(sum1<=num)
    {
        cout<<s<<endl;
        return;
    }
    for(int i=0;i<n;i++)
    {
        a[i].first=s[i]-'a'+1;
        a[i].second=i;
    }
    sort(a,a+n);
    int sum2=0;
    for(int i=0;i<n;i++)
    {
        if(sum2+a[i].first<=num)
        {
            sum2+=a[i].first;
            b[a[i].second]=1;
        }
        else
        break;
    }
    for(int i=0;i<n;i++)
    if(b[i]==1)
    cout<<s[i];
    cout<<endl;
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int Times;
    cin>>Times;
    while(Times--)
    solve();
    return 0;
}

Problem - E

题意:

给你n个二元组,问你能不能把他分成两份,两份里面都含有不一样的数字。还得保证这两份不能双边不能一样。

思路:

首先里面的数字是1-n的,那么每份的数字一定会是1-n,也就是每份二元组的数量一定是n/2的。所以每个数字出现次数就是2次,每个点能到达的也就是两个点(类似于双边的图)。从一个点开始走,路是唯一的,直到遇到已经走过的点,而该点一定是出发点,这样就形成一个闭环,这个闭环点的数量为奇数的话,答案就是NO(欧拉图)。而且这道题我TLE了。原因出现在memset上面。我必须自己把vector数组进行清0。把memset(v,0,sizeof(v));替换为for(int i=1;i<=n;i++) v[i].clear();

代码

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 2e5+10;
#define PI 3.14159265358979323846;
const int INF = 0x3f3f3f3f;
bool vis[maxn];
vector<int> v[maxn];
void solve()
{
    memset(vis,0,sizeof(vis));
    //memset(v,0,sizeof(v));
    int n;
    cin>>n;
    for(int i=1;i<=n;i++)
    v[i].clear();
    for(int i=1;i<=n;i++)
    {
        int x,y;
        cin>>x>>y;
        v[x].push_back(y);
        v[y].push_back(x);
    }
    for(int i=1;i<=n;i++)
        if(v[i].size()!=2)
        {
            cout<<"NO"<<endl;
            return;
        }
    for(int i=1;i<=n;i++)
    {
        int st=i,sum=0;
        while(vis[st]!=1)
        {
            vis[st]=1;
            sum++;
            if(vis[v[st][0]]!=1)
            st=v[st][0];
            else
            st=v[st][1];
        }
        if(sum%2)
        {
            cout<<"NO"<<endl;
            return;
        }
    }
    cout<<"YES"<<endl;
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int Times;
    cin>>Times;
    while(Times--)
    solve();
    return 0;
}

Problem - F

题意:

给你一个序列a与序列b。你可以对序列b里面的元素进行 × 2 \times2 ×2或者 / 2 /2 /2,通过这两种方法能不能将b序列变成a序列。注意,这个序列是没有顺序的。

思路:

奇数是必须由一个数 / 2 /2 /2才能得出来的。而偶数怎么都可以得到。比如假如一个数可以变成 3 3 3,那它一定可以变成 6 , 12 , 24 , 48 6,12,24,48 6,12,24,48.所以我们可以对a序列里面所有的数进行多次 / 2 /2 /2,除到它变成了奇数。然后对于b序列,我们不断对元素 / 2 /2 /2,找到了就匹配的a元素删掉。假如除到最后b的元素都等于0了还没找到,那就说明有个a元素没法被匹配了。则说明无法匹配。

代码

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 2e5+10;
#define PI 3.14159265358979323846;
const int INF = 0x3f3f3f3f;
int a[maxn];
int b[maxn];
map<int,int> mp;
int fun(int a)
{
    while(a%2==0)
    a=a/2;
    return a;
}
void solve()
{
    mp.clear();
    int n;
    cin>>n;
    for(int i=0;i<n;i++)
    {
        cin>>a[i];
        a[i]=fun(a[i]);
        mp[a[i]]++;
    }
    for(int i=0;i<n;i++)
    {
        cin>>b[i];
    }
    for(int i=0;i<n;i++)
    {
        while(b[i]!=0&&mp[b[i]]==0)
        b[i]=b[i]/2;
        if(mp[b[i]]==0)
        {
            cout<<"NO"<<endl;
            return;
        }
        mp[b[i]]--;
    }
    cout<<"YES"<<endl;
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int Times;
    cin>>Times;
    while(Times--)
    solve();
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值