洛谷 P3599 Koishi Loves Construction
思路
一道構造好題。
Task1
能夠看出兩點:
-
第一個數必須是 \(n\)。
因為有 \(x+n\equiv x(\bmod n)\),如果第一個數不是 \(n\),必然會有兩個相鄰的字首和模 \(n\) 的值相等。
-
除了 \(1\) 之外的奇數都不存在正確構造。
當 \(n\) 為奇數時,有
\[\sum\limits_{i=1}^{n-1}i\mod n=\dfrac{n\times(n-1)}{2}\mod n=0 \]
因為已經確定了第一個數為 \(n\),所以一定會衝突。
剩下的 \(n-1\) 個數,可以找到一種為 \(\text{1 -2 3 -4 5...}\) 的方案,保證 \(1\sim n - 1\)
程式碼裡的實現是先輸出第一個數 \(n\),然後輸出第 \(2\sim n\) 個數,如果 \(i\mod2 = 1\) 則輸出 \(n+1-i\),否則輸出 \(i-1\)。
Task2
容易看出:
-
\(n\) 只能是最後一個數。
若 \(n\) 不為最後一個數,那麼在 \(n\) 之後的字首積在模 \(n\) 意義下一定為 \(0\),必定會衝突。
-
\(1\) 只能是第一個數
如果 \(1\) 不是第一個數,那麼就無法出現字首積模 \(n\)
剩下的數,我們的目標是構造一個在模 \(n\) 意義下字首積連續遞增的序列。
那麼一種可行的構造方案是 \(1,\frac{2}{1},\frac{3}{2}...\frac{n}{n-1}\),因此我們只需要求出每個數的逆元,輸出即可。
但是會有無解的情況,那就是不為 \(4\) 的合數一定無解,因為如果 \(n\) 是合數,那麼一定存在小於 \(n\) 的兩個數乘積為 \(n\),所以只有 \(1,4\) 和所有的質數有解。
注意看特判 \(1\) 和 \(4\) 的情況,因為 \(4\nmid 3!\)。
程式碼
/* Name: P3599 Koishi Loves Construction Author: Loceaner Date: 08/09/20 11:24 Description: Debug: */ #include <cmath> #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define int long long using namespace std; const int A = 1e5 + 11; const int B = 1e6 + 11; const int inf = 0x3f3f3f3f; inline int read() { char c = getchar(); int x = 0, f = 1; for ( ; !isdigit(c); c = getchar()) if (c == '-') f = -1; for ( ; isdigit(c); c = getchar()) x = x * 10 + (c ^ 48); return x * f; } int opt, T, inv[A]; inline bool judge(int x) { for (int i = 2; i * i <= x; i++) { if (x % i == 0) return 0; } return 1; } signed main() { opt = read(), T = read(); while (T--) { int n = read(); if (opt == 1) { if (n % 2 && n != 1) puts("0"); else { cout << 2 << " "; cout << n << " "; for (int i = 2; i <= n; i++) { if (i % 2) cout << n + 1 - i << " "; else cout << i - 1 << " "; } puts(""); } } if (opt == 2) { if (n == 1) { puts("2 1"); continue; } if (n == 4) { puts("2 1 3 2 4"); continue; } if (!judge(n)) puts("0"); else { int mod = n; inv[0] = inv[1] = 1; for (int i = 2; i < n; i++) inv[i] = mod - (mod / i) * inv[mod % i] % mod; cout << 2 << " "; for (int i = 1; i < n; i++) cout << i * inv[i - 1] % mod << " "; cout << n << '\n'; } } } }