k进制下处理线性代数问题:2026暑杭电 1012
1012 向量
我们原先要处理的式子是:
u = ( I + k A ) v = v + k A v u − v = k A v u=(I+kA)v=v+kAv\\
u-v=kAv
u = ( I + k A ) v = v + k A v u − v = k A v
我们接下来在 k k k 进制下求解 v v v
为了方便理解,我们可以令 k = 10 k=10 k = 10
不妨记:v = v 0 v 1 ‾ v=\overline{v_0v_1} v = v 0 v 1 ,其实 v 1 v_1 v 1 是个位数,v 0 v_0 v 0 是剩余位数。
显然有
u 0 − v 0 ≡ 0 ( m o d k ) u_0-v_0\equiv 0\pmod k
u 0 − v 0 ≡ 0 ( mod k )
然后我们就可以求出 v 0 v_0 v 0 了。
接下来我们要求十位了,我们只需要把最上面的式子中的所有个位数去掉就可以了!也就是把所有数右移一位,所有十位数变成个位数。
u 0 u 1 ‾ − v 0 v 1 ‾ = k A v 0 v 1 ‾ u 0 u 1 ‾ − v 0 v 1 ‾ = k A ( v 0 ‾ × k + v 1 ‾ ) u 0 u 1 ‾ − v 0 v 1 ‾ = k 2 A ⋅ v 0 ‾ + k A ⋅ v 1 ‾ u 0 − v 0 = k A v 0 + A v 1 ( u 0 − A v 1 ) − v 0 = k A v 0 \begin{align*}
\overline{u_0u_1}-\overline{v_0v_1}&=kA\overline{v_0v_1}\\
\overline{u_0u_1}-\overline{v_0v_1}&=kA(\overline{v_0}\times k+\overline{v_1})\\
\overline{u_0u_1}-\overline{v_0v_1}&=k^2A\cdot \overline{v_0}+kA\cdot\overline{v_1}\\
u_0-v_0&=kAv_0+Av_1\\
(u_0-Av_1)-v_0&=kAv_0
\end{align*}
u 0 u 1 − v 0 v 1 u 0 u 1 − v 0 v 1 u 0 u 1 − v 0 v 1 u 0 − v 0 ( u 0 − A v 1 ) − v 0 = k A v 0 v 1 = k A ( v 0 × k + v 1 ) = k 2 A ⋅ v 0 + k A ⋅ v 1 = k A v 0 + A v 1 = k A v 0
因此我们就可以愉快地递归下去了
一些实现细节(也是我不能完全理解透的地方但勉强在解释):
最后不用判断 u [ i ] u[i] u [ i ] 是否全部位0,因为负数在模意义下一定是无限循环
k p k^p k p 上限设到 2 e 9 2e9 2 e 9 ,如果大了出来就把它减了
在运算过程中,要始终保持 v [ i ] v[i] v [ i ] 为正,通过模意义进行转换
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 #include <bits/stdc++.h> using namespace std;#ifdef LOCAL #define debug(...) fprintf(stdout, ##__VA_ARGS__) #else #define debug(...) void(0) #endif #define int long long inline int read () {int x=0 ,f=1 ;char ch=getchar ();while (ch<'0' ||ch>'9' ){if (ch=='-' )f=-1 ;ch=getchar ();}while (ch>='0' &&ch<='9' ){x=(x<<1 )+ (x<<3 )+(ch^48 );ch=getchar ();}return x*f;} #define Z(x) (x)*(x) #define pb push_back #define fi first #define se second #define N 1000010 int n, m, i, j, k, T;int u[N], x[N], R[N], v[N], U[N]; vector<int >a[N]; int r, pw, flg; signed main () { #ifdef LOCAL freopen ("in.txt" , "r" , stdin); freopen ("out.txt" , "w" , stdout); #endif T = read (); while (T--) { n = read (); k = read (); m = read (); for (i = 1 ; i <= n; ++i) u[i] = U[i] = read (); for (i = 1 ; i <= n; ++i) v[i] = 0 ; for (i = 1 ; i <= n; ++i) a[i].clear (); for (i = 1 ; i <= m; ++i) x[i] = read (); for (i = 1 ; i <= m; ++i) a[x[i]].pb (read ()); for (r = pw = 1 , flg = 0 ; pw <= 2e9 ; ++r) { debug ("u : " ); for (i = 1 ; i <= n; ++i) debug ("%lld " , u[i]); debug ("\n" ); for (i = 1 ; i <= n; ++i) { R[i] = u[i] % k; if (R[i] < 0 ) R[i] = R[i] + k; v[i] += R[i] * pw; } debug ("v : " ); for (i = 1 ; i <= n; ++i) debug ("%lld " , R[i]); debug ("\n" ); if (i <= n) { flg = 1 ; break ; } for (i = 1 ; i <= n; ++i) { u[i] = (u[i] - R[i]) / k; } for (i = 1 ; i <= n; ++i) { for (auto A : a[i]) u[i] -= R[A]; } pw = pw * k; } if (flg == 1 ) { printf ("No Solution\n" ); continue ; } for (i = 1 ; i <= n; ++i) { if (v[i] > 1e9 ) v[i] -= pw; } for (i = 1 ; i <= n; ++i) if (v[i] < -1e9 || v[i] > 1e9 ) break ; if (i <= n) { printf ("No Solution\n" ); continue ; } for (i = 1 ; i <= n; ++i) { int sx = 0 ; for (auto A : a[i]) sx += v[A] * k; if (sx + v[i] != U[i]) break ; } if (i <= n) { printf ("No Solution\n" ); continue ; } for (i = 1 ; i <= n; ++i) printf ("%lld " , v[i]); printf ("\n" ); } return 0 ; }