[XJOI3529] 左右

题目链接:左右

Description

给你一个s数组,一个t数组,你可以对s数组执行以下两种操作
L 操作:每个数等于其左边的数加上自己
R 操作:每个数等于其右边的数加上自己
第一个数的左边是最后一个数,最后一个数的右边是第一个数
对于每个操作,所有的加法是同时进行的,即(new)s[i] = (old)s[i - 1] + (old)s[i]
现在问你s数组能否变成t数组。
数据范围 \(1\le n\le 50, 1\le s_i, t_i\le 10^{15}\)

Solution

引理:只要确定了\(L\)\(R\)的次数,无论按什么顺序操作,最终序列都相同。
我们将这个数列视为一个多项式,并以\(0,1,...,n-1\)作为下标,则:
序列为\(a_0,a_1x,a_2x^2,...,a_{n-1}x^{n-1}\)
\(L\)操作等价于这个式子乘以\((1+x)\),指数对\(n\)取模。
\(R\)操作等价于这个式子乘以\((1+x^{n-1})\),指数对\(n\)取模。
我们发现,\(L\)\(R\)操作的顺序并不影响序列的结果。
那么我们可以暴力枚举\(L\)\(R\)的次数,并且直接模拟即可。
注意到,因为上限是\(10^{15}\),所以最多只需要\(L\)\(R\)操作\(log\)次即可。
复杂度 \(O(n^3)\),跑不满。

Code

// Author: wlzhouzhuan
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#include <bits/stdc++.h>
using namespace std;
 
#define ll long long
#define ull unsigned long long
#define rint register int
#define rep(i, l, r) for (rint i = l; i <= r; i++)
#define per(i, l, r) for (rint i = l; i >= r; i--)
#define mset(s, _) memset(s, _, sizeof(s))
#define pb push_back
#define pii pair <int, int>
#define mp(a, b) make_pair(a, b)
 
inline int read() {
  int x = 0, neg = 1; char op = getchar();
  while (!isdigit(op)) { if (op == '-') neg = -1; op = getchar(); }
  while (isdigit(op)) { x = 10 * x + op - '0'; op = getchar(); }
  return neg * x;
}
inline void print(int x) {
  if (x < 0) { putchar('-'); x = -x; }
  if (x >= 10) print(x / 10);
  putchar(x % 10 + '0');
}
 
const int N = 102;
ll a[N], b[N], n;
ll c[N], d[N];

bool check() {
  for (int i = 1; i <= n; i++) if (c[i] != b[i]) return 0;
  return 1; 
}
int main() {
  cin >> n;
  for (int i = 1; i <= n; i++) cin >> a[i];
  for (int i = 1; i <= n; i++) cin >> b[i];
  for (int a1 = 0; a1 <= 50; a1++) {
    for (int i = 1; i <= n; i++) c[i] = a[i];
    int ok = 1;
    for (int k = 1; k <= a1; k++) {
      for (int i = 1; i <= n; i++) d[i] = c[i] + c[i == 1 ? n : i - 1];
      for (int i = 1; i <= n; i++) {
        c[i] = d[i];
        if (c[i] > b[i]) {
          ok = 0;
          break;
        }
      }
    }
    if (!ok) continue;
    int a2 = 50;
    while (a2--) { 
      if (check()) {
        puts("Yes");
        exit(0);
      }
      for (int i = 1; i <= n; i++) d[i] = c[i] + c[i == n ? 1 : i + 1];
      for (int i = 1; i <= n; i++) {
        c[i] = d[i];
        if (c[i] > b[i]) {
          break;
        }
      }
    } 
  }
  puts("No");
  return 0;
}
posted @ 2020-04-21 20:37  wlzhouzhuan  阅读(183)  评论(0编辑  收藏  举报