ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Lucky Numbers(枚举,计数)

2022-06-13 16:32:39  阅读:178  来源: 互联网

标签:dots 10 int Lucky leq 枚举 Numbers include


题意

给定一个长度为\(N - 1\)的整数序列\(S = (S_1, S_2, \dots, S_{N-1})\)以及\(M\)个不同的被称为幸运数的整数\(X_1, X_2, \dots, X_M\)。

一个长度为\(N\)的整数序列\(A = (A_1, A_2, \dots, A_N)\)满足如下条件时被称为好序列:

  • 对于任意\(i = 1, 2, \dots, N - 1\),有:\(A_i + A_{i + 1} = S_i\)

找到幸运数出现次数最多的好序列,输出幸运数出现次数。

题目链接:https://atcoder.jp/contests/abc255/tasks/abc255_e

数据范围

\(2 \leq N \leq 10^5\)
\(1 \leq M \leq 10\)
\(-10^9 \leq S_i \leq 10^9\)
\(-10^9 \leq X_i \leq 10^9\)
\(X_1 < X_2 < \cdots < X_M\)

思路

常规操作,求一下\(A\)与\(S\)的关系,不妨设\(A_1 = Z\)。

由\(A_1 + A_2 = S_1\)得:\(A_2 = S_1 - Z\);由\(A_2 + A_3 = S_2\)得:\(A_3 = S_2 - S_1 + Z\);\(A_3 + A_4 = S_3\)得:\(A_4 = S_3 - S_2 + S_1 - Z\);......

通过上面的分析,我们发现对于\(i = 1, 2, \dots, N\),有:\(A_i = (-1)^{i + 1}Z + B_i\)。其中对于\(i=2,\dots, N\),\(B_i = -B_{i - 1} + S_{i - 1}\),\(B_1 = 0\)。

现在问题就转化成了:确定\(Z\),使得序列中幸运数字出现次数最多。

我一开始的做法是枚举序列中的每个数字\(A_i\),二重循环枚举所有幸运数字\(X_j\),分别求出当\(A_i\)等于\(X_j\)时,\(Z\)的值。在此之前,分别使用两个map记录加减\(Z\)时的\(B_i\)出现次数(分别表示为\(neg\)和\(pos\)。当\(i\)是奇数时,\(B_i\)放进\(pos\)中;否则,\(B_i\)放进\(neg\)中)。然后,枚举每个幸运数字\(X_k\),推算满足要求的\(B_i\)(当加\(Z\)时,\(B_i = X_k - Z\);当减\(Z\)时,\(B_i = X_k + Z\)),得到出现次数(\(pos[X_k - Z] + neg[X_k + Z]\))。这个做法是\(O(NM^2 \log N)\)的,被卡掉了。

下面介绍正解。我们需要考虑如何优化掉\(O(M)\)的时间复杂度。我们发现,在枚举的过程中,有\(A_i = (-1)^{i + 1}Z + B_i = X_j\),即:\(Z = (-1)^{i + 1}(X_j - B_i)\)。我们令\(Z_{i, j} = (-1)^{i + 1}(X_j - B_i)\)。同时,我们使用map维护\(Z_{i, j}\)的个数。\(Z_{i, j}\)的个数的意义是,当\(A_1 = Z_{i, j}\)时,序列中有多少个元素为幸运数字。

因此,最终答案就是出现次数最多的\(Z_{i, j}\)。时间复杂度为\(O(NM \log NM)\)。

代码

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <map>

using namespace std;

typedef long long ll;

const int N = 100010, M = 15;

int n, m;
ll s[N], x[M];
ll a[N];
map<ll, ll> mp;

int main()
{
    scanf("%d%d", &n, &m);
    for(int i = 1; i < n; i ++) scanf("%lld", &s[i]);
    for(int i = 1; i <= m; i ++) scanf("%lld", &x[i]);
    for(int i = 2; i <= n; i ++) {
        a[i] = -a[i - 1] + s[i - 1];
    }
    ll ans = 0;
    for(int i = 1; i <= n; i ++) {
        for(int j = 1; j <= m; j ++) {
            ll t = x[j];
            ll A;
            if(i % 2 == 0) A = a[i] - t;
            else A = t - a[i];
            mp[A] ++;
        }
    }
    for(auto p : mp) ans = max(ans, p.second);
    printf("%lld", ans);
    return 0;
}

标签:dots,10,int,Lucky,leq,枚举,Numbers,include
来源: https://www.cnblogs.com/miraclepbc/p/16371293.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有