Codeforces Round #640 (Div. 4)(A~G)

A. Sum of Round Numbers(水题)

代码

#include <bits/stdc++.h>
using namespace std;
void fre() { freopen("A.txt", "r", stdin); freopen("Ans.txt","w",stdout); }
void Fre() { freopen("A.txt", "r", stdin);}
#define ios ios::sync_with_stdio(false)
#define Pi acos(-1)
#define pb push_back
#define fi first
#define se second
#define ll long long
#define ull unsigned long long 
#define db double
#define Pir pair<int, int>
#define PIR pair<Pir, Pir>
#define INF 0x3f3f3f3f
#define mod 998244353
const int mxn = (2e5 + 10) * 2;

ll ar[mxn];
ll psum[mxn];
ll pday[mxn];
vector<int> v;

int main()
{
    /* fre(); */
    ios;
    int T;
    /* scanf("%d", &T); */
    cin >> T;
    while(T --)
    {
        v.clear();
        string s;
        cin >> s;
        for(int i = 0; i < s.size(); i ++)
        {
            if(s[i] != '0')
            {
                int ct = s.size() - i - 1;
                v.push_back((s[i] - '0') * pow(10, ct));
            }
        }
        cout << v.size() << endl;
        for(auto x : v)
            cout << x << " ";
        cout << endl;
    }

    return 0;
}


B. Same Parity Summands(水题)

分析

  • 题意
  1. 给我们一个个数n问能否将它拆分为k个奇数或偶数相加
  • 思路
  1. 首先我们在将n拆分成全奇数或偶数的时候,我们把前k-1个拆分出来的数都当成1(最下的奇数拆分成全奇数的时候)或2(最小的偶数,拆分成全偶的时候)
  2. 我们在拆分之前要先分类讨论n是奇数还是偶数,对于这两种情况我们又可进行细分讨论,k是奇数还是偶数,结合n、k 的奇偶情况就可判断拆分出的k个数数是奇数还是偶数(或者两种情况都行),在这个假设的基础上进行判读就行了

代码

#include <bits/stdc++.h>
using namespace std;
void fre() { freopen("A.txt", "r", stdin); freopen("Ans.txt","w",stdout); }
void Fre() { freopen("A.txt", "r", stdin);}
#define ios ios::sync_with_stdio(false)
#define Pi acos(-1)
#define pb push_back
#define fi first
#define se second
#define ll long long
#define ull unsigned long long 
#define db double
#define Pir pair<int, int>
#define PIR pair<Pir, Pir>
#define INF 0x3f3f3f3f
#define mod 998244353
const int mxn = (2e5 + 10) * 2;

ll ar[mxn];
ll psum[mxn];
ll pday[mxn];
vector<int> v;

int main()
{
    /* fre(); */
    int T;
    scanf("%d", &T);
    while(T --)
    {
        int n, k;
        scanf("%d %d", &n, &k);
        if(n % 2)
        {
            if(k % 2)
            {
                if(n >= k)
                {
                    printf("YES\n");
                    for(int i = 1; i < k; i ++)
                        printf("1 ");
                    printf("%d\n", n - k + 1);
                }
                else
                {
                    printf("NO\n");
                }
            }
            else
            {
                printf("NO\n");
            }
        }
        else
        {
            if(k % 2)
            {
                if(n >= 2 * k)
                {
                    printf("YES\n");
                    for(int i = 1; i < k; i ++)
                        printf("2 ");
                    printf("%d\n", n - 2 * k + 2);
                }
                else
                {
                    printf("NO\n");
                }

            }
            else 
            {
                if(n >= k)
                {
                    printf("YES\n");
                    for(int i = 1; i < k; i ++)
                        printf("1 ");
                    printf("%d\n", n - k + 1);
                }
                else
                {
                    printf("NO\n");
                }
            }
        }


    }

    return 0;
}


K-th Not Divisible by n(二分)

分析

  • 题意
  1. 给我们n、k,让我们求 n的第k个不能被n整除的数是多少?
  • 思路
  1. 这一题我们用二分来求解,网上有 通过用“数学”的方法做的
  2. 对于这一题我们可以知道对于某个数n,那么1~x之间的所有数字中能被n整除的个数为x/n,所以不能被整出的数字个数为:x - n / x, 有了这个结论我们在结合n、k 的取值范围: n < = 1 e 9 , k < = 1 e 9 n<=1e9,k<=1e9 ,可以得出二分的上限最大比1e9 多几个数量级,所以我们设二分的上界为1e14,而二分的下界为1,就行了,通过得出的结论我们不断进行二分区间

代码

#include <bits/stdc++.h>
using namespace std;
void fre() { freopen("A.txt", "r", stdin); freopen("Ans.txt","w",stdout); }
void Fre() { freopen("A.txt", "r", stdin);}
#define ios ios::sync_with_stdio(false)
#define Pi acos(-1)
#define pb push_back
#define fi first
#define se second
#define ll long long
#define ull unsigned long long 
#define db double
#define Pir pair<int, int>
#define PIR pair<Pir, Pir>
#define INF 0x3f3f3f3f
#define mod 998244353
const int mxn = (2e5 + 10) * 2;

int main()
{
    /* fre(); */
    int T;
    scanf("%d", &T);
    while(T --)
    {
        ll n, k;
        scanf("%lld %lld", &n, &k);
        ll l = 1, r = 1e12 + 10;
        ll ans = 0;
        while(l <= r)
        {
            ll mid = (l + r) >> 1;
            if(mid - mid / n >= k)
            {
                r = mid - 1;
                ans = mid;
            }
            else
            {
                l = mid + 1;
            }
        }

        printf("%lld\n", ans);
    }

    return 0;
}

D. Alice, Bob and Candies(模拟水题)

分析

  • 思路
  1. 用前缀和、后缀和预处理一下数据,按照题意进行模拟就行了

代码

#include <bits/stdc++.h>
using namespace std;
void fre() { freopen("A.txt", "r", stdin); freopen("Ans.txt","w",stdout); }
void Fre() { freopen("A.txt", "r", stdin);}
#define ios ios::sync_with_stdio(false)
#define Pi acos(-1)
#define pb push_back
#define fi first
#define se second
#define ll long long
#define ull unsigned long long 
#define db double
#define Pir pair<int, int>
#define PIR pair<Pir, Pir>
#define INF 0x3f3f3f3f
#define mod 998244353
const int mxn = 2e5 + 10;

int ar[mxn];
int prf[mxn];
int suf[mxn];

int main()
{
    /* fre(); */
    int T;
    scanf("%d", &T);
    while(T --)
    {
        int n;
        scanf("%d\n", &n);
        prf[0] = suf[n + 1] = 0;
        for(int i = 1; i <= n; i ++)
            scanf("%d", &ar[i]), prf[i] = prf[i - 1] + ar[i];
        for(int i = n; i >= 1; i --)
            suf[i] = suf[i + 1] + ar[i];

        int last = 0;
        int l = 0, r = n + 1;
        int L = 1, R = n;
        int sl = 0, sr = 0;
        int fg = 0;

        while(r - l > 1)
        {
            while(fg % 2 == 0 && L + 1 < R && prf[L] - prf[l] <= last)
                L ++;

            while(fg % 2 == 1 && R - 1 > L && suf[R] - suf[r] <= last)
                R --;

            if(fg % 2 == 0) last = prf[L] - prf[l], sl += last, l = L;
            else            last = suf[R] - suf[r], sr += last, r = R;
            fg ++;
        }
        printf("%d %d %d\n", fg, sl, sr);
    }

    return 0;
}

E. Special Elements(思维)

分析

  • 题意
  1. 这一题给我们一个有n个元素的序列ar,让我们统计符合题意的元素数量(符合题意的元素数量值的是这个元素等于ar序列的一个连续区间中元素的和,这个连续区间的元素个数要>=2)
  • 思路
  1. 这一题我们要先考虑数据范围: n < = 8000 , a r i < = n n<=8000,ar_i<=n ,我们可以看出数据范围还是比较多小的,我们可以考虑暴力一点的方法,
  2. 而且这一题我们可以考虑,“连续区间”这个限制条件,既然是连续我们肯定要考虑用前缀和来维护区间数据,
  3. 有了上面的一些思考,我们可以考虑用 O ( n 2 ) O(n^2) 的算法暴力的求出ar中每个位置所能的产生的子区间和,在用一个桶来统计哪些区间和出现过了,之后在对ar中的n个元素进行一边查询(指的是:这个数在 桶 中是否出现过)就行了

代码

#include <bits/stdc++.h>
using namespace std;
void fre() { freopen("A.txt", "r", stdin); freopen("Ans.txt","w",stdout); }
void Fre() { freopen("A.txt", "r", stdin);}
#define ios ios::sync_with_stdio(false)
#define Pi acos(-1)
#define pb push_back
#define fi first
#define se second
#define ll long long
#define ull unsigned long long 
#define db double
#define Pir pair<int, int>
#define PIR pair<Pir, Pir>
#define INF 0x3f3f3f3f
#define mod 998244353

const int mxn = 8005;
int ar[mxn];
int br[mxn];


int main()
{
    /* fre(); */
    int T;
    scanf("%d", &T);
    while(T --)
    {
        memset(br, 0, sizeof(br));
        int n;
        scanf("%d\n", &n);
        for(int i = 1; i <= n; i ++)
        {
            scanf("%d", &ar[i]);
            ar[i] += ar[i - 1];
        }

        for(int i = 1; i < n; i ++)
            for(int j = i + 1; j <= n; j ++)
            {
                int val = ar[j] - ar[i - 1];
                if(val < mxn) br[val] = 1;
            }
        int ans = 0;
        for(int i = 1; i <= n; i ++)
            if(br[ar[i] - ar[i - 1]]) ans ++;
        printf("%d\n", ans);
    }

    return 0;
}


F. Binary String Reconstruction(构造)

分析

  • 题意
  1. 让我们构造一个0、1字符串,在这个字符串中:
    00子串的数量为n1,
    01、10的子串数量为n2
    11的子串数量为n3
  • 思路
  1. 我觉得对于这种构造题,我们在构造的时候要按照一定的方式、顺序来构造,
  2. 在这题中我们可以,先选择构造有n1个“00”子串的字符串s(这一步构造完之后在这个字符串中有n1 + 1个0),再其次我们可以在字符串s的基础上选择构造有n3个“11”子串的新字符s(在原来的基础上s中有包含了 n3+1个连续的1,s字符串形如:00011111),
  3. 有了上面的构造,使第一个和第三个条件都得到了满足,接下来我们在已经构造出的字符串s的基础上,考虑怎么构造出满足第二个条件的新字符串s吧,对于这一步有些的特殊情况我们需要进行特殊考虑,例如在3. 过程之后构造出的字符串s为:

    s=“0000”,这样并没有产生第二种情况的01、10子串,而且之后我们s的末尾拼接字符的时候是先拼接‘1’,在拼接‘0’
    s=“11111”,这样并没有产生第二种情况的01、10子串,而且之后我们s的末尾拼接字符的时候是先拼接‘0’,在拼接‘1’
    s=“0001111”,这种情况况下已经产生了1个“01”子串,接下来我在拼接字符的时候,拼接的字符需要我们注意

代码

#include <bits/stdc++.h>
using namespace std;
void fre() { freopen("A.txt", "r", stdin); freopen("Ans.txt","w",stdout); }
void Fre() { freopen("A.txt", "r", stdin);}
#define ios ios::sync_with_stdio(false)
#define Pi acos(-1)
#define pb push_back
#define fi first
#define se second
#define ll long long
#define ull unsigned long long 
#define db double
#define Pir pair<int, int>
#define PIR pair<Pir, Pir>
#define INF 0x3f3f3f3f
#define mod 998244353

const int mxn = 8005;

int main()
{
    /* fre(); */
    int T;
    scanf("%d", &T);
    while(T --)
    {
        string s;
        int a, b, c;
        scanf("%d %d %d", &a, &b, &c);
        for(int i = 0; i <= a && a; i ++)
            s += '0';
        for(int i = 0; i <= c && c; i ++)
            s += '1';
        int ct = 0;             //在目前构造的字符串s中是否已经产生的"01"
        if(min(a, c))
            ct = 1;
        b -= ct; 
        char ch1, ch2;
        if(c == 0 && a != 0)
        {
            ch1 = '1';
            ch2 = '0';
        }
        else if(c == 0 && a == 0)
        {
            ch1 = '0';
            ch2 = '1';
            b ++;
        }
        else if(c != 0 && a == 0)
        {
            ch1 = '0';
            ch2 = '1';
        }
        else if(c != 0 && a != 0)
        {
            ch1 = '0';
            ch2 = '1';
        }



        for(int i = 0; i < b && b; i ++)
        {
            if(i % 2 == 0)
                s += ch1;
            else
                s += ch2;
        }
        cout << s << endl;
    }

    return 0;
}

G Special Permutatio(构造+思维)

分析

  • 题意
  1. 然我我们重新排列一个 n个元素的排列,是这个排列相邻元素之间的差值大于等于2,小于等于4.
  • 思路
  1. 我觉得这一题,其实就是找出一种合理的构造方法就行,至于思路我觉得就是找找规律,没有规律自己就胡乱凑凑看,下面就说一种符合题意的构造方法(前提是 n>=4,否则的话是没有符合题意的答案的)
  2. 假如有一个n个数了的排列,我们我们将这个n个数中的所有奇数从大到小排序作为答案序列的前半部分,而剩下的所有偶数中,我们把2、4单独拿出来,按4、2的顺序作为答案序列的中间部分,之后把剩下的偶数按从小到大的顺序排序作为答案序列的后半部分,例如:n = 10 -->构造得: 9 7 5 3 1 4 2 6 8 10 9、7、5、3、1、4、2、6、8、10

代码

#include <bits/stdc++.h>
using namespace std;
void fre() { freopen("A.txt", "r", stdin); freopen("Ans.txt","w",stdout); }
void Fre() { freopen("A.txt", "r", stdin);}
#define ios ios::sync_with_stdio(false)
#define Pi acos(-1)
#define pb push_back
#define fi first
#define se second
#define ll long long
#define ull unsigned long long 
#define db double
#define Pir pair<int, int>
#define PIR pair<Pir, Pir>
#define INF 0x3f3f3f3f
#define mod 998244353

const int mxn = 8005;

int main()
{
    /* fre(); */
    int T;
    scanf("%d", &T);
    while(T --)
    {
        int n;
        scanf("%d\n", &n);
        if(n < 4) 
        {
            printf("-1\n");
            continue;
        }

        for(int i = n; i >= 1; i --)
            if(i % 2)
                printf("%d ", i);

        printf("4 2 ");
        for(int i = 6; i <= n; i ++)
            if(i % 2 == 0)
                printf("%d ", i);
        printf("\n");
    }

    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_34261446/article/details/106428961
今日推荐