暑假牛客多校第六场 2023-8-4(E、G、C)

未补完


E. Sequence


算法:前缀和

做法:我们对于一段区间[l, r]一定要求其总和为偶数才能部分满足题目要求,为奇数则是不可能构造一个或多个区间和都为偶数。另外我们观察b[l - 1],我们发现对于[l, r]中的每个前缀和b[i] \(i \in [l, r]\),我们都有当前a[i]为偶数且a[i]前面的奇数个数为偶数或者a[i]为奇数且a[i]前面的奇数个数加一为偶数时,b[i]必与b[l - 1]同奇偶。当a[i]为奇数或者a[i]为偶数但是a[i]前面的奇数个数为奇数,则b[i]b[l - 1]奇偶性相反。因此我们可以统计[l, r]的前缀和的奇偶个数来确定最大划分区间。

code
#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
#include <map>
#include <queue>
#include <stack>
#include <deque>
#include <cmath>
#include <string>
#include <set>
#define x first
#define y second
using namespace std;

typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int, int> PII;
typedef pair<double, int> PDI;
typedef pair<double, double> PDD;
int dx[4] = { -1, 1, 0, 0 }, dy[4] = { 0, 0, -1, 1 };

const int N = 100010;

int n, q;
LL a[N], b[N], sodd[N], seven[N];

void solve()
{
    cin >> n >> q;
    for (int i = 1; i <= n; i++)
    {
        cin >> a[i];
        b[i] = b[i - 1] + a[i];
        sodd[i] = sodd[i - 1], seven[i] = seven[i - 1];
        if (b[i] % 2 == 0)seven[i]++;
        else sodd[i]++;
    }

    for (int i = 1; i <= q; i++)
    {
        int l, r, k;
        cin >> l >> r >> k;
        if ((b[r] - b[l - 1]) % 2 != 0 || r - l + 1 < k)cout << "NO" << endl;
        else
        {
            if (b[l - 1] % 2 == 0 && seven[r] - seven[l - 1] >= k)cout << "YES" << endl;
            else if (b[l - 1] % 2 != 0 && sodd[r] - sodd[l - 1] >= k)cout << "YES" << endl;
            else cout << "NO" << endl;
        }

    }
}

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

 

G. Gcd


算法:gcd

做法:首先 \(z\)\(0\) 时,只有 \(x\)\(y\)\(0\) 才能成立,\(z\) 大于 \(x\)\(y\) 时不成立。\(x\)\(y\) 等于 \(z\) 时成立,或者 \(x\)\(y\) 的最大公约数能整除 \(z\) 也成立。

code
#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
#include <map>
#include <queue>
#include <stack>
#include <deque>
#include <cmath>
#include <string>
#include <set>
#define x first
#define y second
using namespace std;

typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int, int> PII;
typedef pair<double, int> PDI;
typedef pair<double, double> PDD;
int dx[4] = { -1, 1, 0, 0 }, dy[4] = { 0, 0, -1, 1 };

const int N = 100010;

int gcd(int a, int b)
{
    return b ? gcd(b, a % b) : a;
}

void solve()
{
    int x, y, z;
    cin >> x >> y >> z;
    if (z == 0 && x != 0 && y != 0)cout << "NO" << endl;
    else if (x == z || y == z)cout << "YES" << endl;
    else if (z > x && z > y)cout << "NO" << endl;
    else
    {
        int d = gcd(x, y);
        if (z % d == 0)cout << "YES" << endl;
        else cout << "NO" << endl;
    }
}

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

 

C. idol!!


算法:构造

做法:(简要说一下思路吧,latex公式太难打了QAQ)我们首先观察双阶层,我们可以发现在 \((n - 1)!! * (n)!! = n!\)。那么在 \(n\) 为偶数的双阶层中就可以转化为 \(2!*4!*......*(\frac{n}{2})!\),而奇数转化为 \(3!*5!*......*n!\)。之后的公式转化在懵哥的题解里。我们只要枚举 \(5、25、125......\),对于 \(n\) 为奇数或者 \(n\) 为偶数我们都可以确定首项和公差还有项数,并且最后不完整的项我们可以由规律用 \(O(1)\) 的时间直接算出来。

code
#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
#include <map>
#include <queue>
#include <stack>
#include <deque>
#include <cmath>
#include <string>
#include <set>
#define x first
#define y second
using namespace std;

using i128 = __int128;
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int, int> PII;
typedef pair<double, int> PDI;
typedef pair<double, double> PDD;
int dx[4] = { -1, 1, 0, 0 }, dy[4] = { 0, 0, -1, 1 };

const int N = 100010;

i128 n, k;

i128 read()
{
    char ch;
    i128 res = 0, f = 1;
    ch = getchar();
    if(ch < '0' || ch > '9')f = -1;
    else res = res * 10 + ch - '0';
    while((ch = getchar()) != '\n')res = res * 10 + ch - '0';
    return res * f;
}

void prt(i128 x)
{
    if(!x)return;
    prt(x / 10);
    putchar(x % 10 + '0');
}

void solve()
{
    n = read(); 
    i128 ans = 0;
    
    if(n % 2 == 0)
    {
        for(i128 digit = 5; digit <= n ; digit *= 5)
        {
            i128 p = n / 2; //项数
            i128 fir = digit / 2 + 2; //a1,等差数列首项
            i128 d = digit * 2; //公差
            if(p % digit == 0)
            {
                ans += (p / digit) * (2 * fir + (p / digit - 1) * d) / 2;
            }
            else 
            { 
                i128 q = p / digit; p = p - q * digit; swap(p, q); //p-> 以digit循环的数, q是剩下的数
                i128 x = (p * digit * 2 + 2) / digit; //剩余数的第一个数对 digit 的值
                ans += p * (2 * fir + (p - 1) * d) / 2;
                if(q <= (digit / 2))ans += x * q;
                else ans += x * (digit / 2) + (q - digit / 2) * (x + 1);
            }
        }
        if(ans == 0)cout << 0;
        else prt(ans);
    }
    else 
    {
        for(i128 digit = 5; digit <= n ; digit *= 5)
        {
            i128 p = n / 2;
            i128 fir = (digit / 2 + 1) * 1 + 2;
            i128 d = digit * 2;
            LL sss = 0;
            if(p % digit == 0)
            {
                ans += (p / digit) * (2 * fir + (p / digit - 1) * d) / 2;
                sss += (p / digit) * (2 * fir + (p / digit - 1) * d) / 2;
            }
            else 
            {
                i128 q = p / digit; p = p - q * digit; swap(p, q);
                i128 x = (p * digit * 2 + 3) / digit;
                ans += p * (2 * fir + (p - 1) * d) / 2;
                sss += p * (2 * fir + (p - 1) * d) / 2;
                if(q <= (digit / 2 - 1))ans += x * q, sss += x * q;
                else ans += x * (digit / 2 - 1) + (q - (digit / 2 - 1)) * (x + 1), sss +=  x * (digit / 2 - 1) + (q - (digit / 2 - 1)) * (x + 1);
            }
        }
        if(ans == 0)cout << 0 << endl;
        else prt(ans);
    }
}

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);
    int t = 1;
    while (t--)
    {
        solve();
    }
    return 0;
}
posted @ 2023-08-05 22:17  dkdklcx  阅读(29)  评论(0)    收藏  举报