题目传送门
题目大意
给定将$\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 }