L. Coordinate Paper(CCPC 长春)构造

L. Coordinate Paper

构造一个长度为 n n n的序列 a a a,满足 a i ≥ 0 a_i \geq 0 ai0 ∑ i = 1 n a i = s \sum\limits_{i = 1} ^{n} a_i = s i=1nai=s,对于任意的 i ∈ [ 1 , n − 1 ] i \in [1, n - 1] i[1,n1],都有 a i − a i + 1 = k   o r   a i + 1 − a i = 1 a_i - a_{i + 1} = k\ or\ a_{i + 1} - a{i} = 1 aiai+1=k or ai+1ai=1,其中 n , s , k n, s, k n,s,k是给定的数。

假定所有的 a i a_i ai都满足 a i + 1 − a i = 1 a_{i + 1} - a_{i} = 1 ai+1ai=1,则对于一个给定的 a 1 a_1 a1,有 ∑ i = 1 n a i = n × a 1 + n ( n − 1 ) 2 \sum\limits_{i = 1} ^{n} a_i = n \times a_1 + \frac{n(n - 1)}2 i=1nai=n×a1+2n(n1),考虑 a i − a i + 1 = k a_i - a_{i + 1} = k aiai+1=k ∑ i = 1 n a i = n × a 1 + n ( n − 1 ) 2 − x ( k + 1 ) \sum\limits_{i = 1} ^{n} a_i = n \times a_1 + \frac{n(n - 1)}2- x (k + 1) i=1nai=n×a1+2n(n1)x(k+1)

考虑对所有数 ( m o d k + 1 ) \pmod {k + 1} (modk+1)下找到一个解,满足 ∑ i = 1 n a i ( m o d k + 1 ) ≡ s ( m o d k + 1 ) \sum\limits_{i = 1} ^{n} a_i \pmod {k + 1} \equiv s \pmod {k + 1} i=1nai(modk+1)s(modk+1)

考虑同余下的一个最小解, a 1 , a 1 + 1 , … , k , 0 , 1 , 2 , … , k , 0 , 1 , 2 , … a_1, a_1 + 1, \dots, k, 0, 1, 2, \dots, k, 0, 1, 2, \dots a1,a1+1,,k,0,1,2,,k,0,1,2,,如果满足 s u m ≤ s   a n d   s u m ( m o d k + 1 ) ≡ s ( m o d k + 1 ) sum \leq s \ and\ sum \pmod{k + 1} \equiv s \pmod{k + 1} sums and sum(modk+1)s(modk+1),则说明找到一组解。

获得最小解后,凑得答案,只需每次对最小得加 k + 1 k + 1 k+1,这样可以保证变动之后这个数比其前方的大 1 1 1,后面的比其小 k k k,满足要求。

#include <bits/stdc++.h>

using namespace std;

const int N = 1e5 + 10;

int n, k, flag;

long long s, a[N];

vector<int> pos[N];

inline int add(int x, int y) {
  return x + y < k + 1 ? x + y : x + y - k - 1;
}

void solve() {
  for (int i = 1; i <= n; i++) {
    a[i] = add(a[i - 1], i != 1);
    pos[a[i]].push_back(i);
  }
  int x = a[1], len = min(k - x + 1, n), last = n - len;
  long long sum = 1ll * (x + x + len - 1) * len / 2;
  sum += 1ll * (last / (k + 1)) * (0 + k) * (k + 1) / 2;
  last %= k + 1;
  sum += 1ll * (0 + 0 + last - 1) * last / 2;
  s -= sum;
  sum = s / (k + 1);
  long long tot = sum / n, more = sum % n;
  for (int i = 1; i <= n; i++) {
    a[i] += 1ll * (k + 1) * tot;
  }
  for (int i = 0; i <= k; i++) {
    for (auto it : pos[i]) {
      if (more) {
        a[it] += k + 1;
        more--;
      }
    }
  }
  for (int i = 1; i <= n; i++) {
    printf("%lld%c", a[i], i == n ? '\n' : ' ');
  }
}

bool judge(int x) {
  int len = min(k - x + 1, n), last = n - len;
  long long sum = 1ll * (x + x + len - 1) * len / 2;
  sum += 1ll * (last / (k + 1)) * (0 + k) * (k + 1) / 2;
  last %= k + 1;
  sum += 1ll * (0 + 0 + last - 1) * last / 2;
  return sum <= s && s % (k + 1) == sum % (k + 1);
}

int main() {
  // freopen("in.txt", "r", stdin);
  // freopen("out.txt", "w", stdout);
  cin >> n >> k >> s;
  for (int i = 0; i <= k; i++) {
    if (judge(i)) {
      flag = 1;
      a[0] = i;
      solve();
      break;
    }
  }
  if (!flag) {
    puts("-1");
  }
  return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值