• Codeforces Round 606 Div2


    A

    题意

    给一个n,求范围[1,n]内所有数中,所有数位都相等的数的个数,如111,22,3

    思路

    求出n的位数d,则数位长度为[1,n-1]的数各有9个,再考虑数位长度为n的数,从高位向低位推,设最高位数字为k,如果当前位等于k,则继续往下推。否则,若大于k,则最可取k个,若小于,则只能取k-1个。最后计算一下答案。

    代码

    #include<bits/stdc++.h>
    
    using namespace std;
    
    int d[15];
    
    int main()
    {
        int T;
        cin>>T;
        while(T--)
        {
            int n,len=0;
            scanf("%d",&n);
            while(n)
            {
                d[len++]=n%10;
                n/=10;
            }
            int res=0,flag=0;
            for(int i=len-2;i>=0;i--)
            {
                if(d[i]==d[len-1])
                    continue;
                if(d[i]<d[len-1])
                    flag=1;
                break;
            }
            res=d[len-1]-flag+9*(len-1);
            printf("%d
    ",res);
        }
    }
    

    B

    题意

    给定一个序列,有奇有偶。偶数k可以通过一次操作变为k/2。所有相同的k可以用一次操作同时变为k/2。求使得整个序列全部为奇数所需要的最少操作次数。

    思路

    k/2等价于k>>1,所以很容易可以想到对于同一个奇数所扩展出来的偶数,只需要取最大所需操作即可,如12,6,都由3扩展而来,对12进行一次操作会得到两个6,再一次操作即可完成目标。所以方法就很明确了,扫一遍序列,记录一下当前数由那个奇数扩展而来,然后用map记录一下最大值,最后加起来就好了。

    代码

    #include<bits/stdc++.h>
    
    using namespace std;
    const int MAX=2e5+5;
    
    int odd[MAX];
    map<int,int>mp;
    
    int main()
    {
        int T;
        cin>>T;
        while(T--)
        {
            int n,x,len=0,res=0;
            mp.clear();
            scanf("%d",&n);
            for(int i=0;i<n;i++)
            {
                scanf("%d",&x);
                if(x&1)continue;
                int cur=0;
                while((x&1)==0)
                    x>>=1,cur++;
                if(!mp[x])
                    odd[len++]=x;
                mp[x]=max(mp[x],cur);
            }
            for(int i=0;i<len;i++)
                res+=mp[odd[i]];
            printf("%d
    ",res);
        }
    }
    

    C

    题意

    给一个字符串,每次操作可以去掉一个字符,求最少操作数使得整个字符串不包含任何onetwo子串。

    思路

    很显然,除了twone这种情况可以一次操作去掉两个以外,对于每一个onetwo子串都得操作一次,所以先扫一遍,去除twone这种子串的o,再扫一遍去除单独的onetwo,对于单独的这种应该删除中间的字符,因为删除两边的可以会接上,如oonee这种。

    代码

    #include<bits/stdc++.h>
    
    using namespace std;
    const int MAX=2e5+5;
    
    char s[MAX];
    int res[MAX];
    
    int main()
    {
        int T;
        cin>>T;
        while(T--)
        {
            scanf("%s",s);
            int cnt=0,len=strlen(s);
            for(int i=2;i<len-2;i++)
                if(s[i]=='o')
                    if(s[i-1]=='w'&&s[i-2]=='t'&&s[i+1]=='n'&&s[i+2]=='e')
                        s[i]='k',res[cnt++]=i;
            for(int i=1;i<len-1;i++)
            {
                if(s[i]=='w'&&s[i-1]=='t'&&s[i+1]=='o')
                    res[cnt++]=i;
                if(s[i]=='n'&&s[i-1]=='o'&&s[i+1]=='e')
                    res[cnt++]=i;
            }
            printf("%d
    ",cnt);
            for(int i=0;i<cnt;i++)
                printf("%d ",res[i]+1);
            printf("
    ");
        }
    }
    

    D

    题意

    给一堆字符串,仅由01组成,每个字符串不重复,然后玩玩接龙,1结尾的接1开头的,以此类推。但是这些字符串可能无法完全拼接在一起。所以给一种操作,每次操作可以翻转某一个字符串,但是必须保证所有字符串不重复。求是否可以使得所有字符串拼接在一起,可以则输出操作次数,否则输出-1

    思路

    很显然字符串有4种,根据开头结尾记为01,10,00,110011型可以忽略,因为可以不影响结果地接到0110型上。所以只考虑0110型。当且仅当两者数量差距小于等于1时可以完全拼接,所以记录一下数量,然后多出来的一半的翻转分配过去就好了。再用哈希记录一下翻转后的字符串是否出现过,若出现过,则不可翻转,往下推。再特判一下两者数量全为0的情况就可以了。3s时间挺充裕的,所以直接用STL实现。

    代码

    #include<bits/stdc++.h>
    
    using namespace std;
    const int MAX=4e6+6;
    
    vector<pair<int,string> >v01,v10;
    unordered_map<string,bool>mp01,mp10;
    vector<int>out;
    
    void init()
    {
        out.clear();
        v01.clear();
        v10.clear();
        mp01.clear();
        mp10.clear();
    }
    
    int main()
    {
        int T;
        cin>>T;
        while(T--)
        {
            int n,a=0,b=0,c=0,d=0;
            string s;
            init();
            scanf("%d",&n);
            for(int i=1; i<=n; i++)
            {
                cin>>s;
                int len=s.size();
                if(s[0]==s[len-1])
                {
                    if(s[0]=='0')
                        c++;
                    else
                        d++;
                    continue;
                }
                if(s[0]=='0')
                    a++,v01.push_back(make_pair(i,s)),mp01[s]=1;
                if(s[0]=='1')
                    b++,v10.push_back(make_pair(i,s)),mp10[s]=1;
            }
            if(a==b)
            {
                if(a!=0)
                    printf("0
    
    ");
                else
                {
                    if(c==0||d==0)
                        printf("0
    
    ");
                    else
                        printf("-1
    
    ");
                }
                continue;
            }
            int ch=abs(a-b)/2,res=abs(a-b)/2;
            if(a<b)
                for(int i=0; i<v10.size(); i++)
                {
                    if(ch==0)break;
                    s=v10[i].second;
                    reverse(s.begin(),s.end());
                    if(mp01[s])continue;
                    out.push_back(v10[i].first);
                    ch--;
                }
            else
                for(int i=0; i<v01.size(); i++)
                {
                    if(ch==0)break;
                    s=v01[i].second;
                    reverse(s.begin(),s.end());
                    if(mp10[s])continue;
                    out.push_back(v01[i].first);
                    ch--;
                }
            if(ch!=0)
            {
                printf("%-1
    
    ");
                continue;
            }
            printf("%d
    ",res);
            for(int i=0; i<out.size(); i++)
                printf("%d ",out[i]);
            printf("
    ");
        }
    }
    

    E

    题意

    给一个无向图,再给出两节点a,b,求有多少点对x,y满足从xy必定经过这两个节点。

    思路

    理想情况是a,b直接相连,他们的连边为此无向图的割边。此时答案即为a,b各自连接的节点个数之积。可以在此情况上做一下拓展。得到如下模型。

    根据此模型我们可以看出,只需要计算a不经过b能到达的节点数,b不经过a能到的的节点数,再排除掉共同可达的节点数就可以变为理想模型。所以用dfs计数即可。注意一下极限情况乘积可能会溢出。

    代码

    #include<bits/stdc++.h>
    
    using namespace std;
    const int MAX=2e5+5;
    typedef long long ll;
    
    vector<int>G[MAX];
    int vis[MAX],common;
    
    ll dfs(int x,int t,int k)
    {
        if(x==t)return 0;
        if(vis[x]&&vis[x]!=k)
            common++;
        vis[x]=k;
        ll ans=1;
        for(int i=0; i<G[x].size(); i++)
            if(vis[G[x][i]]!=k)
                ans+=dfs(G[x][i],t,k);
        return ans;
    }
    
    int main()
    {
        int T;
        cin>>T;
        while(T--)
        {
            int n,m,a,b;
            scanf("%d%d%d%d",&n,&m,&a,&b);
            for(int i=1; i<=n; i++)
                G[i].clear(),vis[i]=0;
            common=0;
            while(m--)
            {
                int u,v;
                scanf("%d%d",&u,&v)`;
                G[u].push_back(v);
                G[v].push_back(u);
            }
            ll aa=dfs(a,b,1)-1,bb=dfs(b,a,2)-1;
            printf("%I64d
    ",(aa-common)*(bb-common));
        }
    }
    
  • 相关阅读:
    Sybase:游标用法以及嵌套用法
    EasyUI:获取某个dategrid的所有行数据
    EasyUI:所有的图标
    Sybase:SAP IQ学习笔记
    Sybase:SybaseIQ的几个系统过程
    Sybase:解锁
    Python3:文件读写
    Android Studio 1.0.2 设置内存大小
    关于Android的margin(当前视图与周围视图的距离)和padding(当前视图与内部内容的距离)
    《Android Studio开发实战 从零基础到App上线》资源下载和内容勘误
  • 原文地址:https://www.cnblogs.com/cryingrain/p/12337700.html
Copyright © 2020-2023  润新知