首页 > 其他分享 >2022 ICPC 济南站 E - Identical Parity // exgcd

2022 ICPC 济南站 E - Identical Parity // exgcd

时间:2022-11-28 11:55:21浏览次数:128  
标签:Identical Parity le int mid exgcd large mod

题目来源:2022 International Collegiate Programming Contest, Jinan Site E

题目链接:https://codeforces.com/gym/104076/problem/E


题意

有 \(T\) 组案例,对于每个案例:

给定整数 \(n\)、\(k\),问是否存在一种 \([1,n]\) 的排列,使得对于该排列所有长度为 \(k\) 的子区间,它们区间和的奇偶性相同。

数据范围:\(1 \le T \le 10^5\),\(1 \le k \le n \le 10^9\).

思路:exgcd

可以视作有一个长度为 \(k\) 的移动窗口,每次只会进入连续的 \(k\) 个数,那么其往后移动一格时,就会弹出一个数,同时进入一个数,若要使得奇偶性保持不变,那么这两个数的奇偶性是需要一致的,于是满足条件的排列,应该满足:\(p_i\ mod\ 2 \equiv p_{i+k}\ mod\ 2\),其中 \(1 \le i \le n - k\)。

于是整个排列可以按照 \(i\ mod\ k\) 的值,划分成 \(k\) 块,我们需要为每个块分配奇偶性,其中,包含数字数量为 \(\lfloor \frac{\large n}{\large 2} \rfloor\) (记为 \(a\))的块的数量为 \(k - n\ mod\ k\)(记为 \(p\)),包含数字数量为 \(\lfloor \frac{\large n}{\large 2} \rfloor + 1\) (记为 \(b\))的块的数量为 \(n\ mod\ k\)(记为 \(q\))。

我们需要解决的问题实际上就是,找到一组整数解 \((x,y)\),使得 \(xa + yb = \lfloor \frac{\large n}{\large 2} \rfloor\),\(x \in [0,p]\),\(y \in [0,q]\) 同时成立。这个等式和取值限制的意义是,能找到一组合法的分配方案,使得取偶数的块的数字总数量等于 \([1,n]\) 范围内的偶数数量。

对于这个等式,可以用 exgcd 求得一组解 \((x_0,y_0)\),由于 \(gcd(a,b)=1\),那么通解就是 \((x_0 + m·b,y_0-m·a)\),根据两个取值范围的限制,可以二分或者公式,分别求出 \(m\) 的取值范围 \([l_x,r_y]\),\([l_y,r_y]\),判断 \(max(l_x,l_y) \le min(r_x,r_y)\) 是否成立即可。

时间复杂度:\(O(T·logn)\).

代码

#include <bits/stdc++.h>
#define int long long
using namespace std;

int exgcd(int a, int b, int& x, int& y)
{
    if(!b) {
        x = 1, y = 0;
        return a;
    }
    int d = exgcd(b, a % b, x, y);
    int tmp = x;
    x = y, y = tmp - a / b * y;
    return d;
}

void solve()
{
    int n, k;
    cin >> n >> k;

    int a = n / k, p = k - n % k;
    int b = n / k + 1, q = n % k;

    int x, y;
    int d = exgcd(a, b, x, y);

    if(n / 2 % d) {
        cout << "No" << '\n';
        return;
    }

    x = x / d * (n / 2), y = y / d * (n / 2);

    int l = -1e9, r = 1e9;
    int l1 = r;
    while(l <= r) {
        int mid = l + r >> 1;
        if(x + mid * (b / d) >= 0) r = mid - 1, l1 = mid;
        else l = mid + 1;
    }

    l = -1e9, r = 1e9;
    int r1 = l;
    while(l <= r) {
        int mid = l + r >> 1;
        if(x + mid * (b / d) <= p) l = mid + 1, r1 = mid;
        else r = mid - 1;
    }

    l = -1e9, r = 1e9;
    int l2 = r;
    while(l <= r) {
        int mid = l + r >> 1;
        if(y - mid * (a / d) <= q) r = mid - 1, l2 = mid;
        else l = mid + 1;
    }

    l = -1e9, r = 1e9;
    int r2 = l;
    while(l <= r) {
        int mid = l + r >> 1;
        if(y - mid * (a / d) >= 0) l = mid + 1, r2 = mid;
        else r = mid - 1;
    }

    cout << (max(l1, l2) <= min(r1, r2) ? "Yes" : "No") << '\n';
}

signed main()
{
    cin.tie(0);
    ios::sync_with_stdio(false);

    int test;
    cin >> test;
    while(test--) solve();

    return 0;
}

标签:Identical,Parity,le,int,mid,exgcd,large,mod
From: https://www.cnblogs.com/jakon/p/16931801.html

相关文章

  • 裴蜀定理、exgcd与有理数取余
    裴蜀定理exgcd之前写得不好所以重写一遍exgcd即扩展欧几里得算法,常用来求\(ax+by=\gcd{(a,b)}\)的一组解。设一组解为\(x_1,y_1\),即\(ax_1+by_1=\gcd{(a,......
  • 【模板】二元一次不定方程 exgcd
    postedon2022-09-1715:59:26|under模板|sourcecodeLLmod(LLx,LLm){return(x%m+m)%m;}LLexgcd(LLa,LLb,LLc,LL&x,LL&y){ if(!b)returnx=c/a,y=0,a;......
  • 裴蜀定理、Exgcd与乘法逆元
    目录裴蜀定理Exgcd扩展欧几里得算法例题:P5656,exgcd模板题裴蜀定理逆元并非对任何数存在……定理:\(ax+by=c\)有解\(\{x,y\}\)当且仅当\(c\)是\(\gcd(a,b)\)的倍......
  • P5656 【模板】二元一次不定方程 (exgcd)
    P5656【模板】二元一次不定方程(exgcd)\[ax+by=d\\ax_1+by_1=c\\x_1=\frac{x*c}{gcd(a,b)},y_1=\frac{y*c}{gcd(a,b)}\\对于最小正整数解有:x_1+\lambda\frac{b}{gcd......
  • 浅谈 Exgcd 和同余问题
    \[\large\text{本以为学的是数学专题,实际上学的是}\]\[\huge\stackrel{\text{xuán}}{\textbf{数}}\textbf{学专题}\]玄学专题\(\Huge\textbf{1}\\small\text{Exgcd(扩......