• Educational Codeforces Round 81 (Rated for Div. 2)


    A. Display The Number

    题目链接:

    http://codeforces.com/contest/1295/problem/A

    题意:

      一个显示屏,你可以显示很多数字通过亮起一堆段段闪瞎别人的dog眼,比如亮起一个数字1,需要亮起两段,亮起一个数字2,需要亮起5段(如题目图)

      你最多可以亮起n段,问你可以显示最大的数字是多少。

    分析:

      用book[i]表示亮起数字i所需的段数,有: book[10]={6,2,5,5,4,5,6,3,7,6};

      发现数字1需要的段最少,要让数字最大,首先他的位数要尽可能多,于是我们把尽量多的段去显示更多的1。

      这时候如果n是偶数,就显示了 n/2 个1 ; 如果n是奇数,可以显示 n/2 个1 ,同时还剩下一个段,这时候可以把开头的1改成 7 ,book[ 1 ] = 2 ,book[ 7 ] = 3 , n就刚好用完。

      这样就可以保证数字是最大的。

    代码:

    #include <bits/stdc++.h>
    using namespace std;
    const int maxn = 1e6 + 10;
    #define ll long long
    #define ios std::ios::sync_with_stdio(false)
    const ll INF(0x3f3f3f3f3f3f3f3fll);
    const int inf(0x3f3f3f3f);
    ll book[10] = {6, 2, 5, 5, 4, 5, 6, 3, 7, 6};
    int main()
    {
        ios;
    
        ll t;
        cin >> t;
        while (t--)
        {
            ll n; ///不超过n位的
            cin >> n;
            if (n % 2 == 0)
            {
                for (int i = 0; i < n / 2; i++)
                {
                    cout << 1;
                }
            }
            else
            {
                cout << 7;
                for (int i = 0; i < n / 2 - 1; i++)
                {
                    cout << 1;
                }
            }
            cout << '
    ';
        }
        return 0;
    }
    View Code

    B. Infinite Prefixes

    题目链接:

    https://codeforces.com/contest/1295/problem/B

    题意:

      给你字符串长度n和x,然后给你长度为n的字符串s,s只包含0和1,字符串t是s的长度无限的重复串,比如s=01001,t是01001 01001.... 

      然后问你 t 的某个前缀中 (0的数量 - 1的数量 ==x) 问这样的前缀有多少个。

    分析:

      满足条件的t的前缀,一定是由

      ①若干个的整个儿的字符串s(也可不包含)

      ②长度为 0~n的s的前缀 

      这两部分组成的,所以只要计算:

      ①字符串s中 cnt=0的数量 - 1的数量

      ②字符串s的前缀中 cnt_i[i]=前i个字符中,0的数量 - 1的数量

      判断条件是 (x-cnt_i[i])%cnt == 0  即由若干个s和s的前i个字符组成的字符串满足条件 ans++;

    代码:

    #include <bits/stdc++.h>
    using namespace std;
    const int maxn = 1e6 + 10;
    #define ll long long
    #define ios std::ios::sync_with_stdio(false)
    const ll INF(0x3f3f3f3f3f3f3f3fll);
    const int inf(0x3f3f3f3f);
    int main()
    {
        ios;
        ll t;
        cin >> t;
        while (t--)
        {
            ll n, x;
            cin >> n >> x;
            string a;
            cin >> a;
            ll cnt_i[maxn];
            ll cnt0 = 0, cnt1 = 0;
            for (ll i = 0; i < a.size(); i++)
            { ///计算前缀中cnt(0)-cnt(1),保存在cnt_i[i]中
                if (a[i] == '0')
                    cnt0++;
                else
                    cnt1++;
    
                cnt_i[i] = cnt0 - cnt1;
            }
    
            ll cnt = cnt0 - cnt1; ///整个字符串s的cnt(0)-cnt(1)
            if (cnt == 0)
            { ///如果1和0的数量相当
                if (x == 0)
                {
                    cout << -1 << endl;
                    continue;
                }
                else
                {
                    int c = 0;
                    for (int i = 0; i < a.size(); i++)
                    {
                        if (cnt_i[i] == x)
                        { ///cnt*任意个+cnt_i[i]==x ,由于cnt==0,忽略
                            c++;
                        }
                    }
                    if (c == 0)
                    {
                        cout << 0 << endl;
                        continue;
                    }
                    else
                    { ///如果存在cnt_i[i]==x  又cnt=0,无数个
                        cout << -1 << endl;
                        continue;
                    }
                }
            }
            else
            {
                int c = 0;
                if (x == 0)
                    c++; ///空前缀的情况
                for (int i = 0; i < a.size(); i++)
                    if (((x - cnt_i[i]) % cnt == 0) && (x - cnt_i[i]) / cnt >= 0)
                        c++; ///(x-cnt_i[i])/cnt>=0,因为cnt(0)-cnt(1)有正有负,所以要判断一下
                cout << c << endl;
            }
        }
        return 0;
    }
    View Code

    C. Obtain The String

    题目链接:

    https://codeforces.com/contest/1295/problem/C

    题意:

      给你两个字符串s和t,有一个空串z,你可以疯狂的把s的任何子序列加到字符串z后面,使得z==t,问你最小操作次数。

    分析:

      就是问你怎么用s的子序列瞎鸡儿最有顺序的构造z。

      首先,如果t中有一个字符,不存在于s中,当然不能构造啦,所以输出-1。

      然后呢,我们遍历字符串z,当遍历到z[i]的时候,我们找s串里有没有z[i](肯定有啦,没有的都-1了),他的位置在哪里呢?设z[i]在s中的位置在pos(z[i])(说不定有很多个啦,先定义有一个好了)

      ①pos(z[i])>pos(z[i-1])  okk,z[i]选定完成啦!

      ②pos(z[i])<pos(z[i-1])  omg,选不了了,我上个字母选的位置 在 我现在想选的位置的后面啊 ,怎么办呢,结束当前子序列的添加,开始选下一个子序列,而下一个子序列的头 就是我现在想选的位置啦。

      因为字符串都只包含小写字母,所以我们用vector[26]记录'a'~'z'每个字母,都存在s中的哪些位置。

      然后用一个pre 记录,我上一次选的位置,now 记录,我这次想选的位置,如果now>pre,选定成功,反正,结束当前子序列,开始加下一个子序列。

      因为每个字母会存在很多位置,所以用二分查找是否有大于pre的。

    代码:

    #include <bits/stdc++.h>
    using namespace std;
    const int maxn = 2e5 + 10;
    #define ll long long
    #define ios std::ios::sync_with_stdio(false)
    const ll INF(0x3f3f3f3f3f3f3f3fll);
    const int inf(0x3f3f3f3f);
    int main()
    {
        ios;
        ll t;
        cin >> t;
        while (t--)
        {
            int ans = 0;
            string t, s;
            cin >> s >> t;
            vector<int> pos[26];
            for (int i = 0; i < s.size(); i++)
            { ///记位置
                pos[s[i] - 'a'].push_back(i);
            }
    
            bool ok = true;
            int pre = -1;
            for (int i = 0; i < t.size(); i++)
            {
                int temp = t[i] - 'a';
                if (pos[temp].empty())
                { ///如果没这个字母
                    ok = false;
                    break;
                }
                int now = lower_bound(pos[temp].begin(), pos[temp].end(), pre) - pos[temp].begin();
                if (now == pos[temp].size()) ///没找到比pre大的
                {
                    ans++;                    ///重新开始
                    pre = pos[temp][0] + 1; ///+1是为了避免连续字母找重复
                }
                else
                {
                    pre = pos[temp][now] + 1;
                }
            }
            if (!ok)
            {
                cout << -1 << '
    ';
            }
            else
            {
                cout << ans + 1 << '
    '; ///+1是因为最后的子序列的最后一个字符不会满足now==pos[temp].size()即ans少+1嘞
            }
        }
        return 0;
    }
    View Code

    D. Same GCDs

    题目链接:

    https://codeforces.com/contest/1295/problem/D

    题意:

      给你a和b,让你计算有多少个x(0<=x<m)使得gcd(a,b)=gcd(a+x,b)

    分析:

      说实话这题咋一看完全没思路啊,后来被my candy,一个憨憨一个大佬提点才会做QAQ

      是这样的首先,假设有两个数a,b,且gcd(a,b)=1,即a,b互质 , 那我要让gcd(a,b)=gcd(a+x,b)=1,只要找出有多少个数和b互质(数的范围在[0,b))对8?

      没错, 找出和b互质的数有多少个 差不多这样就行了

      可是gcd(a,b)不一定等于1呀 ?

      但是gcd(a/gcd(a,b),b/gcd(a,b)) 一定等于 1 啊

      于是乎,就变成了 找出有多少和 b/gcd(a,b) 互质的数(数的范围在[0,b/gcd(a,b))),而且这个数就是答案啦

      就变成了求欧拉函数的问题了。

    代码:

    #include <bits/stdc++.h>
    using namespace std;
    const int maxn = 2e5 + 10;
    #define ll long long
    #define ios std::ios::sync_with_stdio(false)
    const ll INF(0x3f3f3f3f3f3f3f3fll);
    const int inf(0x3f3f3f3f);
    long long gcd(long long b, long long c) //计算最大公约数
    {
        return c == 0 ? b : gcd(c, b % c);
    }
    int main()
    {
        ios;
        ll t;
        cin >> t;
        while (t--)
        {
            ll a, m;
            cin >> a >> m;
            ll res = gcd(a, m);
            a /= res, m /= res;
            ll ans = m;
            for (ll i = 2; i * i <= m; i++)
            {
                if (m % i == 0)
                {
                    ans -= ans / i;
                    while (m % i == 0)
                        m /= i;
                }
            }
            if (m > 1)
                ans -= ans / m;
            cout << ans << endl;
        }
        return 0;
    }
    View Code

    看了别人的代码发现自己真是个大蒟蒻,所以:

    代码和E题看这里->https://www.cnblogs.com/StarRoadTang/p/12249128.html

  • 相关阅读:
    c++中单引号和双引号的区别
    C++ 数组
    C++ 输出到文本文件
    C++中文本的读入
    C++ 输入和输出
    C++构造函数和文件组织
    Linux中使用gcc编译文件
    linux下修改gcc编译器版本
    Git--创建与合并分支
    'webpack' 不是内部或外部命令,也不是可运行的程序 或批处理文件。
  • 原文地址:https://www.cnblogs.com/GoodVv/p/12249839.html
Copyright © 2020-2023  润新知