Codeforces 1045B Space Isaac - 数论 - Hash

题目传送门

  传送门I

  传送门II

  传送门III

题目大意

  给定将$\left \{ 0, 1, \dots, m - 1\right \}$分成了不相交的两个非空集合$A$和$B$,给定$A$,问存在多少个整数$x$满足$0\leqslant x < m$且对于任意$a\in A, b \in B$满足$a + b\not \equiv x \pmod{m}$

  容易发现满足后一个条件的充分必要条件是对于任意$a \in A$,存在$a' \in A$使得$a + a' \equiv x \pmod{m}$。

  如果$a \leqslant x$,则易证$a' \leqslant x$。

  同样,如果$a > x$,则易证$a' > x$。

  所以这个数$x$将序列分成两部分,每一部分首尾配对后,每一对的和都等于$x$。

  那么怎么判断呢?我们发现$a + d = c + b$等价于$a - b = c - d$。

  所以我们只用差分一下判断是否是回文,再判断首尾的和是否等于$x$就行了。

Code

 1 /**
 2  * Codeforces
 3  * Problem#1045B
 4  * Accepted
 5  * Time: 77ms
 6  * Memory: 7300k
 7  */
 8 #include <algorithm>
 9 #include <iostream>
10 #include <cstdlib>
11 #include <cstdio>
12 #include <vector>
13 using namespace std;
14 typedef bool boolean;
15 
16 #define ull unsigned long long
17 
18 const int N = 2e5 + 5;
19 const ull base = 1e9 + 7;
20 
21 int n, M;
22 int ar[N];
23 int cr[N];
24 ull ph[N], sh[N], pb[N];
25 
26 int add(int a, int b) {
27     return ((a += b) >= M) ? (a - M) : (a);
28 }
29 
30 inline void init() {
31     scanf("%d%d", &n, &M);
32     for (int i = 1; i <= n; i++)
33         scanf("%d", ar + i);
34 }
35 
36 ull fquery(int l, int r) {    // forward
37     if (l > r)
38         return 0;
39     return ph[r] - ph[l - 1] * pb[r - l + 1];
40 }
41 
42 ull rquery(int l, int r) {    // backward
43     if (l > r)
44         return 0;
45     return sh[l] - sh[r + 1] * pb[r - l + 1];
46 }
47 
48 boolean ispar(int l, int r) {
49     return fquery(l, r) == rquery(l, r);
50 }
51 
52 vector<int> vec;
53 
54 inline void solve() {
55     ph[0] = 0, sh[n] = 0, pb[0] = 1;
56     for (int i = 1; i < n; i++)
57         ph[i] = ph[i - 1] * base + (cr[i] = ar[i + 1] - ar[i]);
58     for (int i = n - 1; i; i--)
59         sh[i] = sh[i + 1] * base + cr[i];
60     for (int i = 1; i < n; i++)
61         pb[i] = pb[i - 1] * base;
62 
63     for (int i = 1, x; i < n; i++) {
64         x = ar[1] + ar[i];
65 //        if (x >= M)
66 //            break;
67         if (add(ar[i + 1], ar[n]) == x && ispar(1, i - 1) && ispar(i + 1, n - 1))
68             vec.push_back(x);
69     }
70     int x = add(ar[1], ar[n]);
71     if ((x <= ar[1] || x >= ar[n]) && ispar(1, n - 1))
72         vec.push_back(x);
73     printf("%d\n", (signed) vec.size());
74     sort(vec.begin(), vec.end());
75     for (int i = 0; i < (signed) vec.size(); i++)
76         printf("%d ", vec[i]);
77     putchar('\n');
78 }
79 
80 int main() {
81     init();
82     solve();
83     return 0;
84 }
posted @ 2018-10-18 07:54 阿波罗2003 阅读(...) 评论(...) 编辑 收藏