• Codeforces Round #606 (Div. 2, based on Technocup 2020 Elimination Round 4)


    B

    给定一个数列,每次操作选择一个偶数cc,把所有与cc相同的数都除以22,重复此类操作,直到所有数都变为奇数,问最小的操作次数。

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int maxn=2e5+10;
    int a[maxn];
    ll n;
    unordered_map<int,int>vis;
    bool cmp(int a,int b){
        return a>b;
    }
    int main()
    {
    	ll  t;
    	cin>>t;
    	while(t--){
            cin>>n;
            vis.clear();
            ll ans=0;
            for(int i=1;i<=n;i++)cin>>a[i];
            sort(a+1,a+1+n,cmp);
            for(int i=1;i<=n;i++){
                if(vis[a[i]]==0&&(a[i]&1)==0){
                    vis[a[i]]=1;
                    while(a[i]){
                        ans++;a[i]/=2;vis[a[i]]=1;
                        if(a[i]&1) break;
                    }
                }
            }
            cout<<ans<<endl;
    	}
    }
    

      C

    给定一个字符串,要求去掉若干个字母,使得该字符串不包含"one""one"和"two""two",求最小的去掉字符的数量。

    有以下三个情况:

    (1):one,ooone这种,那直接取消n或者e,而不是o

    (2):two,twooo这种,那直接取消t或者w,而不是o

    (3)twone直接取消o;

    用kmp先匹配twone,因为先匹配one和two的话twone这个还得再搞一次。

    #include <bits/stdc++.h>
    #define MIN(a,b) ((((a)<(b)?(a):(b))))
    #define MAX(a,b) ((((a)>(b)?(a):(b))))
    #define ABS(a) ((((a)>0?(a):-(a))))
    using namespace std;
     
    template <typename T>
    void read(T &x) {
        int s = 0, c = getchar();
        x = 0;
        while (isspace(c)) c = getchar();
        if (c == 45) s = 1, c = getchar();
        while (isdigit(c)) x = (x << 3) + (x << 1) + (c ^ 48), c = getchar();
        if (s) x = -x;
    }
     
    template <typename T>
    void write(T x, char c = ' ') {
        int b[40], l = 0;
        if (x < 0) putchar(45), x = -x;
        while (x > 0) b[l++] = x % 10, x /= 10;
        if (!l) putchar(48);
        while (l) putchar(b[--l] | 48);
        putchar(c);
    }
     
    char one[4]={"one"};
     
    char two[4]={"two"};
     
    char twone[6]={"twone"};
     
    int nxtone[4],nxttwo[4],nxttwone[6];
     
    const int N=2e5+8;
     
    char s[N];
     
    int len,cnt;
     
    int anspos[N];
     
    void makenext(char qaq[],int nxt[],int n){
        nxt[0]=0;
        int k=0;
        for (int i=1;i<n;i++){
            while ((k>0)&&(qaq[k]!=qaq[i])) k=nxt[k-1];
            if (qaq[k]==qaq[i]) k++;
            nxt[i]=k;
        }
    }
     
    void kmp(char qaq[],int nxt[],char qwq[],int n){
        int q=0;
        for (int i=0;i<len;i++){
            if (qwq[i]=='@') continue;
            while ((qwq[i]!=qaq[q])&&(q>0)) q=nxt[q-1];
            if (qwq[i]==qaq[q]) q++;
            if (q==n) {
                if (n==5) {qwq[i-2]='@'; anspos[++cnt]=i-1;}
                else {qwq[i-1]='@'; anspos[++cnt]=i;}
            }
        }
    }
     
    void Input(void) {
        cnt=0;
        scanf("%s",s);
        len=strlen(s);
    }
     
    void Solve(void) {
        kmp(twone,nxttwone,s,5);
        kmp(two,nxttwo,s,3);
        kmp(one,nxtone,s,3);
    }
     
    void Output(void) {
        write(cnt,'
    ');
        for(int i=1;i<=cnt;++i) printf("%d%c",anspos[i],i==cnt?'
    ':' ');
        if (cnt==0) puts("");
    }
     
    main(void) {
        int kase;
        read(kase);
        makenext(one,nxtone,3);
        makenext(two,nxttwo,3);
        makenext(twone,nxttwone,5);
        for (int i = 1; i <= kase; i++) {
            //printf("Case #%d: ", i);
            Input();
            Solve();
            Output();
        }
    }
    

      D

    题目大意

    给定若干个互不相同的0101子串,现翻转一些子串,使得这些子串可以排成一行,第一个子串任意,然后前一个子串的末数字和后一个子串的首数字一样,且不能有相同的子串。求最小的翻转次数,且输出任一种对应的方案。无解则输出1−1

    解题思路

    考虑到只涉及子串的首位和末位,我们按照首位和末位的数字将这些子串分为44类,即00,01,10,1100,01,10,11串。
    无解的情况就是有0000串和1111串但无1010和0101串。
    由植树原理知只要1010串和0101串的数量差值小于等于11即可。
    因为0101串翻转就是1010串,那么最小的操作次数就是1010和0101串的数量差的一半下取整。但这里可能会出现翻转后的子串与已有的子串相同。
    因为0000串和1111串无需翻转,我们就不用考虑它们。
    注意到如果一个0101串翻转后与已有的子串相同,这个已有的子串一定是1010串,且可以和翻转的0101串进行匹配,我们就可以不考虑这对子串了。

    #include <bits/stdc++.h>
    #define MIN(a,b) ((((a)<(b)?(a):(b))))
    #define MAX(a,b) ((((a)>(b)?(a):(b))))
    #define ABS(a) ((((a)>0?(a):-(a))))
    using namespace std;
    
    const int N=2e5+8;
    
    int num[4],s01[N],s10[N];
    
    int n,l,c0,c1;
    
    string s,ss;
    
    unordered_map<string,pair<int,bool>> qwq;
    
    void Input(void) {
        qwq.clear();
        num[0]=num[1]=num[2]=num[3]=0;
        c0=c1=0;
        cin>>n;
        for(int i=1;i<=n;++i){
            cin>>s;
            if (s[0]==s[s.size()-1]) {qwq[s]=make_pair(i,1);continue;}
            ss=s;
            reverse(s.begin(),s.end());
            if (qwq[s].second==1) {qwq[s].second=0;++num[2];++num[3];continue;}
            qwq[ss]=make_pair(i,1);
        }
    }
    
    void Solve(void) {
        for(auto v:qwq){
            if (v.second.second==1){
            const char *ss=v.first.c_str();
                l=strlen(ss);
                if (l==1) ++num[ss[0]-'0'];
                else{
                    if (ss[0]=='0'&&ss[l-1]=='0') ++num[0];
                    else if (ss[0]=='0'&&ss[l-1]=='1') ++num[2],s01[++c0]=v.second.first;
                    else if (ss[0]=='1'&&ss[l-1]=='0') ++num[3],s10[++c1]=v.second.first;
                    else ++num[1];
                }
            }
        }
        if (num[2]==0&&num[3]==0&&num[0]!=0&&num[1]!=0) cout<<"-1"<<endl;
        else {
            int qwq=ABS(num[2]-num[3]);
            qwq/=2;
            cout<<qwq<<endl;
            if (num[2]>num[3]) for(int i=1;i<=qwq;++i) cout<<s01[i]<<(i==qwq?'
    ':' ');
            else for(int i=1;i<=qwq;++i) cout<<s10[i]<<(i==qwq?'
    ':' ');
            if (qwq==0) cout<<'
    ';
        }
    }
    
    void Output(void) {}
    
    main(void) {
        ios::sync_with_stdio(false);
        int kase;
        freopen("input.txt", "r", stdin);
        freopen("output.txt", "w", stdout);
        cin>>kase;
        for (int i = 1; i <= kase; i++) {
            //printf("Case #%d: ", i);
            Input();
            Solve();
            Output();
        }
    }
    

      E

    题目大意

    给定一张nn个点mm条边的无向图,有两个特殊城市a,ba,b,求点对数(x,y)(x,y),使得从城市xx到城市yy的所有路径中都会经过城市aa和bb,其中xx与yy均不等于aa和bb。

    解题思路

    我们考虑城市aa和bb,很容易想到一种情形就是aa和bb把它们之间的点形成了孤岛,这样从aa的另外一边的城市到bb的另外一边的城市就必须经过aa和bb了。而aa,bb就成了连接它们的割点。
    那么我们就对aa进行DFSDFS,记录aa不经过bb所能到达的城市,有cntacnta个,然后再从bb进行DFSDFS,不经过aa,如果到达了aa所到达的城市,那么这个城市就是孤岛上的城市,记有dd个,否则就是aa所到达不到,即bb的另一边的城市,记有cntbcntb个,而a的另一边的城市有cntadcnta−d个。

    #include <bits/stdc++.h>
    #define MIN(a,b) ((((a)<(b)?(a):(b))))
    #define MAX(a,b) ((((a)>(b)?(a):(b))))
    #define ABS(a) ((((a)>0?(a):-(a))))
    using namespace std;
    
    template <typename T>
    void read(T &x) {
        int s = 0, c = getchar();
        x = 0;
        while (isspace(c)) c = getchar();
        if (c == 45) s = 1, c = getchar();
        while (isdigit(c)) x = (x << 3) + (x << 1) + (c ^ 48), c = getchar();
        if (s) x = -x;
    }
    
    template <typename T>
    void write(T x, char c = ' ') {
        int b[40], l = 0;
        if (x < 0) putchar(45), x = -x;
        while (x > 0) b[l++] = x % 10, x /= 10;
        if (!l) putchar(48);
        while (l) putchar(b[--l] | 48);
        putchar(c);
    }
    
    const int N=2e5+8;
    
    vector<int> edge[N];
    
    int n,m,a,b;
    
    int sign[N];
    
    long long cnta,cntb;
    
    void Input(void) {
        read(n);
        read(m);
        read(a);
        read(b);
        for(int i=1;i<=n;++i) edge[i].clear();
        for(int u,v,i=1;i<=m;++i){
            read(u);
            read(v);
            edge[u].push_back(v);
            edge[v].push_back(u);
        }
    }
    void DFSa(int x){
        for(auto i:edge[x]){
            if (i==b) continue;
            if (sign[i]==0){
                sign[i]=1;
                ++cnta;
                DFSa(i);
            }
        }
    }
    void DFSb(int x){
        for(auto i:edge[x]){
            if (i==a) continue;
            if (sign[i]!=2){
                if (sign[i]==1) --cnta;
                else ++cntb;
                sign[i]=2;
                DFSb(i);
    //            continue;
            }
    
        }
    }
    void Solve(void) {
        for(int i=1;i<=n;++i) sign[i]=0;
        cnta=cntb=0;
        sign[a]=1;
        DFSa(a);
        sign[b]=2;
        DFSb(b);
    }
    void Output(void) {
        write(cntb*cnta,'
    ');
    }
    int main(void) {
        //ios::sync_with_stdio(false);
        int kase; read(kase);
        for (int i = 1; i <= kase; i++) {
            //printf("Case #%d: ", i);
            Input();
            Solve();
            Output();
        }
        return 0;
    }
    

      


    那么答案就是(cntad)cntb(cnta−d)∗cntb.

  • 相关阅读:
    并行编译 Xoreax IncrediBuild
    FreeImage使用
    wxWidgets简单的多线程
    wx菜单栏
    #你好Unity3D#Hierarchy视图监听gameObject点击事件
    #你好Unity3D#Project脚本执行双击资源操作
    Unity3D研究院编辑器之Editor的GUI的事件拦截
    Unity3D研究院编辑器之脚本设置ToolBar
    Unity3D研究院编辑器之不影响原有布局拓展Inspector
    Unity3D研究院之Editor下监听Transform变化
  • 原文地址:https://www.cnblogs.com/hgangang/p/12209955.html
Copyright © 2020-2023  润新知