洛谷提高模拟赛2

比赛链接 ()[https://www.luogu.org/contestnew/show/11251]

T1

捕获7.PNG

显然排序后每一个豆子都在上一个的右下角
排序后组合数统计步数就可以了

知识点补充:组合数统计步数 在dx+dy步中 选dx步向下走 其余向右走

标程

#include <bits/stdc++.h>

using namespace std;

const int MAXN = 200005;
const int MOD = (int)1e9 + 7;

int n, m, k, fac[MAXN], inv[MAXN];

struct Point {
  int x, y;
  bool operator<(const Point & rhs) const {
    return x + y < rhs.x + rhs.y;
  }
}P[MAXN];

int fexp(int x, int y) {
  int res = 1;
  for(int i = 1; i <= y; i <<= 1) {
    if(i & y) res = 1LL * res * x % MOD;
    x = 1LL * x * x % MOD;
  }
  return res;
}

void init(int n) {
  fac[0] = inv[0] = 1;
  for(int i = 1; i <= n; i++) {
    fac[i] = 1LL * fac[i - 1] * i % MOD;
    inv[i] = fexp(fac[i], MOD - 2);
  }
}

int C(int n, int m) {
  assert(n >= m);
  return 1LL * fac[n] * inv[m] % MOD * inv[n - m] % MOD;
}

int main() {
  scanf("%d %d %d", &n, &m, &k);
  init(200000);
  for(int i = 1; i <= k; i++) {
    scanf("%d %d", &P[i].x, &P[i].y);
  }
  P[++k] = Point{1, 1};
  P[++k] = Point{n, m};
  sort(P + 1, P + k + 1);
  int ans = 1;
  for(int i = 2; i <= k; i++) {
    int dx = P[i].x - P[i - 1].x;
    int dy = P[i].y - P[i - 1].y;
    if(dx < 0 || dy < 0) {
      ans = 0;
      break;
    }
    ans = 1LL * ans * C(dx + dy, dx) % MOD;
  }
  printf("%d\n", ans);
  return 0;
}

T2

捕获7.PNG

想到了统计不满足的 但是没有解决重叠问题
正解:树链剖分扫描线
子树dfn连续嘛

T3

捕获7.PNG

有一个奇妙的思路
计算每一个b[i]与对应a[i]的位置差绝对值之和tot
然后找到最大的i使得2*(i - 1)是tot的约数且i不大于n

然鹅爆零

出题者本意是要练大家打表找规律。。。
注:要学会用程序打表哦 【吐血

不知道题目给出操作是什么效果时 打表吧

部分分:循环同构 kmp

知识点补充:即在s1后续一个s1 然后拿s2在里面kmp

一堆大讨论。。。
n是奇数:ans = n - 1
n是偶数:
数列是排列且逆序对有偶数个 ans = n - 2
数列是排列且逆序对有奇数个 ans = n - 1
有重复 ans = n - 1

打表及标程如下

//打表

#include <bits/stdc++.h>

using namespace std;

int solve(int n, int k) {
  string s;
  for(int i = 1; i <= n; i++) {
    s += (char)(i + '0');
  }
  queue<string> Q;
  map<string, int> vis;
  Q.push(s);
  vis[s] = 1;
  while(!Q.empty()) {
    string cur = Q.front(); Q.pop();
    for(int i = 0; i < cur.size(); i++) {
      // [i, i + k - 1]
      if(i + k - 1 >= cur.size()) break;
      string nx = cur;
      for(int j = i + k - 1; j > i; j--) {
        swap(nx[j], nx[j - 1]);
      }
      if(!vis[nx]) {
        Q.push(nx);
        vis[nx] = 1;
      }
    }
  }
  return vis.size();
}

int main() {
  int n = 9;
  for(int k = 2; k <= 9; k++) {
    cerr << solve(n, k) << endl;
  }
  return 0;
}

//标程:
#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

bool checkNull(const vector<int> & a, const vector<int> & b) {
  vector<int> A(a), B(b);
  sort(A.begin(), A.end());
  sort(B.begin(), B.end());
  return A != B;
}

int circularMin(const vector<int> & a) {
  int n = a.size();
  vector<int> s(a.size() + a.size());
  for(int i = 0; i < s.size(); i++) {
    s[i] = a[i % a.size()];
  }
  int i = 0, j = 1, k;
  while(i < n && j < n) {
    for(k = 0; s[i + k] == s[j + k]; k++);
    if(k >= n) break;
    if(s[i + k] > s[j + k]) i += k + 1;
    else j += k + 1;
    if(i == j) j++;
  }
  return i < j ? i : j;
}

bool checkN(const vector<int> & a, const vector<int> & b) {
  int p1 = circularMin(a);
  int p2 = circularMin(b);
  for(int i = 0; i < a.size(); i++) {
    if(a[p1] != b[p2]) return false;
    p1 = (p1 + 1) % a.size();
    p2 = (p2 + 1) % a.size();
  }
  return true;
}

bool checkUnique(const vector<int> & a) {
  vector<int> A(a);
  for(int i = 1; i < A.size(); i++) {
    if(A[i] == A[i - 1]) return false;
  }
  return true;
}

ll calc(const vector<int> & a) {
  int n = a.size();
  vector<int> p(a);
  sort(p.begin(), p.end());
  p.erase(unique(p.begin(), p.end()), p.end());
  vector<int> A(n);
  for(int i = 0; i < n; i++) {
    A[i] = lower_bound(p.begin(), p.end(), a[i]) - p.begin() + 1;
  }
  vector<int> c(n + 1);
  auto sum = [&](int x) {
    int ret = 0;
    for(; x >= 1; x -= x & -x) ret += c[x];
    return ret;
  };
  auto add = [&](int x, int y) {
    for(; x <= n; x += x & -x) c[x] += y;
  };
  ll res = 0;
  for(int i = n - 1; i >= 0; i--) {
    res += sum(A[i] - 1);
    add(A[i], 1);
  }
  return res;
}

int main() {
  int T;
  cin >> T;
  while(T--) {
    int n;
    cin >> n;
    vector<int> a(n), b(n);
    for(int i = 0; i < n; i++) cin >> a[i];
    for(int i = 0; i < n; i++) cin >> b[i];
    if(checkNull(a, b)) {
      cout << -1 << endl;
    } else if(checkN(a, b)) {
      cout << n << endl;
    } else {
      if(n % 2 == 0 && checkUnique(a)) {
        int p1 = calc(a) % 2;
        int p2 = calc(b) % 2;
        if(p1 == p2) {
          cout << n - 1 << endl;
        } else {
          cout << n - 2 << endl;
        }
      } else {
        cout << n - 1 << endl;
      }
    }
  }
  return 0;
}

附赠万能头 #include <bits/stdc++.h>

猜你喜欢

转载自www.cnblogs.com/hjmmm/p/9786442.html
今日推荐