博主詐屍啦c++
雖然一輪以後就退役了可是二輪仍是要去劃劃水呀~函數
然鵝學了不到一個月文化課再回來看OI的東西有一種恍如隔世的感受,烤前感受也沒啥可複習的,就補一補去年二輪的題吧。ui
題目思路基本都參考自shadowice神仙Orzspa
Day2T1沒時間作了咕咕咕debug
充滿毒瘤氣息的計算幾何題。。指針
首先旋轉一下座標系,那麼只須要考慮兩條線平行於\(y\)軸的狀況。code
因爲題目中規定每一個擋板都不和直線導軌接觸,所以必定是分別分佈於\(y > 0\)和\(y < 0\)兩部分,咱們分別維護。blog
如今只考慮上半部分,不難看出對於兩條線段一上一下的狀況,上面的線段被遮擋的部分是沒有用的。同時全部的線段咱們能夠拆成加入和刪除兩個事件,首先預處理出兩個事件之間的最大的sec,同時有了距離就能夠算出答案。排序
而後雙指針掃一下。遊戲
複雜度\(O(n \log n)\)
#include<bits/stdc++.h> #define fi first #define se second #define LL long long #define pb push_back #define double long double using namespace std; const int MAXN = 1e6 + 10; template <typename A, typename B> inline bool chmin(A &a, B b){if(a > b) {a = b; return 1;} return 0;} template <typename A, typename B> inline bool chmax(A &a, B b){if(a < b) {a = b; return 1;} return 0;} inline int read() { char c = getchar(); int x = 0, f = 1; while(c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();} while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar(); return x * f; }; int N, opt[MAXN]; double x[MAXN][2], y[MAXN][2], pos[MAXN], bx, by, ex, ey, L; double nx, val[MAXN], sec[MAXN]; struct Segment { int id; bool operator < (const Segment &rhs) const { if(id == rhs.id) return 0; int td = rhs.id; double va = (y[id][1] - y[id][0]) / (x[id][1] - x[id][0]) * (nx - x[id][0]) + y[id][0]; double vb = (y[td][1] - y[td][0]) / (x[td][1] - x[td][0]) * (nx - x[td][0]) + y[td][0]; return abs(va) < abs(vb); } }; set<Segment> su, sd; double GouGu(double x, double y) { return sqrt(x * x + y * y); } int comp(int a, int b) { return (a < 0 ? x[-a][1] : x[a][0]) < (b < 0 ? x[-b][1] : x[b][0]); } void init() { nx = 0; memset(val, 0, sizeof(val)); } void solve() { N = read(); init(); for(int i = 1; i <= N; i++) { x[i][0] = read(); y[i][0] = read(); x[i][1] = read(); y[i][1] = read(); } bx = read(), by = read(); ex = read(); ey = read(); L = read(); double dx = ex - bx, dy = ey - by, dis = GouGu(dx, dy); double bl = (bx == by) ? 0 : by - dy / dx * bx; for(int i = 1; i <= N; i++) y[i][0] -= bl, y[i][1] -= bl; dx /= dis; dy /= dis;//dx cos dy sin //(x, y) for(int i = 1; i <= N; i++) { double px1 = x[i][0], px2 = x[i][1], py1 = y[i][0], py2 = y[i][1]; x[i][0] = dx * px1 + dy * py1; //tag y[i][0] = dx * py1 - dy * px1; x[i][1] = dx * px2 + dy * py2; y[i][1] = dx * py2 - dy * px2; if(x[i][0] > x[i][1]) swap(x[i][0], x[i][1]), swap(y[i][0], y[i][1]); sec[i] = GouGu(x[i][1] - x[i][0], y[i][1] - y[i][0]) / (x[i][1] - x[i][0]); } for(int i = 1; i <= 2 * N; i++) opt[i] = (i <= N ? -i : i - N); sort(opt + 1, opt + 2 * N + 1, comp); for(int i = 1; i <= 2 * N; i++) { int u; if(opt[i] > 0) {//insert u = opt[i]; nx = pos[i] = x[u][0]; (y[u][0] > 0 ? su : sd).insert({u}); } else {//delet u = -opt[i]; nx = pos[i] = x[u][1]; (y[u][0] > 0 ? su : sd).erase({u}); } if(!su.empty()) val[i] += sec[su.begin()->id]; if(!sd.empty()) val[i] += sec[sd.begin()->id]; } for(int i = 2 * N; i >= 1; i--) val[i] = val[i- 1]; double ret = 0, rl = pos[1] - L, rr = pos[1], ans = 0; int pl = 1, pr = 2; while(pr <= 2 * N) { double dl = pos[pl] - rl, dr = pos[pr] - rr; if(dl > dr) ret += (val[pr] - val[pl]) * dr, pr++, rl += dr, rr += dr; else if(dr > dl) ret += (val[pr] - val[pl]) * dl, pl++, rl += dl, rr += dl; else ret += (val[pr] - val[pl]) * dl, pr++, pl++, rl += dl, rr += dl; ans = max(ans, ret); } printf("%.15Lf\n", ans); } signed main() { for(int T = read(); T--; solve()); return 0; }
首先建出圓方樹,那麼答案爲包含全部詢問點的最小聯通塊大小 減去關鍵點個數
最小聯通塊大小能夠轉化爲邊的貢獻最後特判LCA,將全部點按dfs序排序後算出相鄰兩點的dis,最後/2便可
複雜度\(O(n log n)\)
#include<bits/stdc++.h> #define Pair pair<int, int> #define MP(x, y) make_pair(x, y) #define fi first #define se second //#define int long long #define LL long long #define pb push_back #define Fin(x) {freopen(#x".in","r",stdin);} #define Fout(x) {freopen(#x".out","w",stdout);} using namespace std; const int MAXN = 1e6 + 10, mod = 1e9 + 7; const LL INF = 1e18 + 10; const double eps = 1e-9; template <typename A, typename B> inline bool chmin(A &a, B b){if(a > b) {a = b; return 1;} return 0;} template <typename A, typename B> inline bool chmax(A &a, B b){if(a < b) {a = b; return 1;} return 0;} template <typename A, typename B> inline LL add(A x, B y) {if(x + y < 0) return x + y + mod; return x + y >= mod ? x + y - mod : x + y;} template <typename A, typename B> inline void add2(A &x, B y) {if(x + y < 0) x = x + y + mod; else x = (x + y >= mod ? x + y - mod : x + y);} template <typename A, typename B> inline LL mul(A x, B y) {return 1ll * x * y % mod;} template <typename A, typename B> inline void mul2(A &x, B y) {x = (1ll * x * y % mod + mod) % mod;} template <typename A> inline void debug(A a){cout << a << '\n';} template <typename A> inline LL sqr(A x){return 1ll * x * x;} inline int read() { char c = getchar(); int x = 0, f = 1; while(c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();} while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar(); return x * f; } int N, M, nd; vector<int> v[MAXN], E[MAXN]; int dfn[MAXN], low[MAXN], times, st[MAXN], tp; void tarjan(int x, int fa) { dfn[x] = low[x] = ++times; st[++tp] = x; for(auto &to : v[x]) { if(to == fa) continue; if(!dfn[to]) { tarjan(to, x), chmin(low[x], low[to]); if(low[to] >= dfn[x]) { E[++nd].pb(x); E[x].pb(nd); do { E[nd].pb(st[tp]); E[st[tp]].pb(nd); }while(st[tp--] != to); } } else chmin(low[x], dfn[to]); } } int dis[MAXN], siz[MAXN], son[MAXN], top[MAXN], dep[MAXN], ffa[MAXN]; void dfs(int x, int fa) { siz[x] = 1; ffa[x] = fa; for(auto &to : E[x]) { if(to == fa) continue; dis[to] = dis[x] + (to <= N); dep[to] = dep[x] + 1; dfs(to, x); siz[x] += siz[to]; if(siz[to] > siz[son[x]]) son[x] = to; } } void dfs2(int x, int topf) { top[x] = topf; dfn[x] = ++times; if(!son[x]) return ; dfs2(son[x], topf); for(auto &to : E[x]) { if(top[to]) continue; dfs2(to, to); } } int LCA(int x, int y) { while(top[x] ^ top[y]) { if(dep[top[x]] < dep[top[y]]) swap(x, y); x = ffa[top[x]]; } return dep[x] < dep[y] ? x : y; } int Dis(int x, int y) { return dis[x] + dis[y] - 2 * dis[LCA(x, y)]; } int comp(int a, int b) { return dfn[a] < dfn[b]; } void init() { for(int i = 1; i <= N; i++) v[i].clear(); for(int i = 1; i <= nd; i++) E[i].clear(); #define m0(x) memset(x, 0, sizeof(x)) m0(top); m0(dfn); m0(low); m0(dis); m0(dep); m0(son); m0(ffa); m0(siz); m0(dis); #undef m0 tp = 0; times = 0; nd = 0; } int ggg = 0; void solve() { N = read(); M = read(); init(); nd = N; for(int i = 1; i <= M; i++) { int x = read(), y = read(); v[x].pb(y); v[y].pb(x); } tarjan(1, 0); dfs(1, 0); dfs2(1, 1); int Q = read(); for(int k = 1; k <= Q; k++) { int num = read(); LL ans = 0; vector<int> po; for(int i = 1; i <= num; i++) po.pb(read()); sort(po.begin(), po.end(), comp); for(int i = 0; i < po.size() - 1; i++) { ans += Dis(po[i], po[i + 1]); } ans += Dis(po[num - 1], po[0]); ans = ans / 2 + (LCA(po[0], po[num - 1]) <= N) - num; cout << ans << '\n'; } } signed main() { for(int T = read(); T--; solve()); return 0; }
神仙反演Orzzzzzzzzzz
首先一個串的本質不一樣的輪換個數是不重疊最小循環節的長度
若是最小循環節的長度\(d\)是偶數,此時一個迴文串的\(d\)種不一樣的輪換字符串當中剛好有兩個迴文串(自己一個,把前\(\frac{d}{2}\)個字符拼到後面一個)
不然\(d\)是奇數的話必定會有\(d\)個本質不一樣的字符串
首先考慮字符集爲\(k\)的狀況下回文串的數量\(g(n)\)
顯然\(g(n) = k^{\lfloor\frac{n+1}{2} \rfloor}\)(固定一半)
那麼設
$$
\begin{cases}
h(i) = &i &(i \equiv 1 \pmod 2)\
&\frac{i}{2} &(Otherwise)
\end{cases}
$$
設\(f(i)\)表示最小循環節爲\(i\)的字符串數量,顯然有
\(Ans(n) = \sum_{d|n} h(d) f(d)\)
\(f(d)\)很難直接求,可是咱們能夠枚舉循環節獲得一個等式
\[g(n) = \sum_{d|n} f(d)\]
反演一下
\[f(n) = \sum_{d|n} \mu(d) g(\frac{n}{d})\]
帶入原來的公式
\[ Ans(n) = \sum_{d|n} h(d) \sum_{k |d} \mu(k) g(\frac{d}{k}) \]
咱們嘗試枚舉\(g\)
\[ Ans(n) = \sum_{k|n} g(k) \sum_{k|d\text{且}d|n} h(d) \mu(\frac{d}{k}) \]
把\(d\)拆爲\(d = d' * K\),咱們去枚舉新的\(d'\)
\[ Ans(n) = \sum_{k|n} g(k) \sum_{d|\frac{n}{k}} h(k d) \mu(d) \]
以前咱們發現\(h\)函數有比較好的性質,這裏彷佛能夠直接把\(d\)提出來。分析一下不難發現,只有當\(d\)是偶數且\(k\)是奇數是不能直接提。由於一個奇數不會有偶數因子,那麼\(\frac{n}{k}\)必定是偶數
此時把式子中的\(k\)提出來,考慮一下\(k\sum_{d|\frac{n}{k}} h(d)\mu(d)\)的值,打一下表能夠發現值老是\(0\),由於\(2\)這個因子使得\(mu\)爲\(\pm 1\)的項消掉了
那麼在計算這時候直接把這種狀況判掉就能夠
原式變爲
\[ Ans(n) = \sum_{k|n} g(k)h(k) \sum_{d|\frac{n}{k}} d\mu(d) \]
而後直接對\(n\)進行Pollard-Rho分解,分解的同時能夠求出後面的值,拿個map存一下。
而後dfs枚舉約數直接算就好了
複雜度玄學,可是出題人把\(n\)出到\(10^{18}\)也只能這麼幹。。
#include<bits/stdc++.h> #define fi first #define se second #define int long long #define LL long long #define pb push_back using namespace std; const int MAXN = 1e6 + 10; const LL INF = 1e18 + 10; int mod; template <typename A, typename B> inline bool chmin(A &a, B b){if(a > b) {a = b; return 1;} return 0;} template <typename A, typename B> inline bool chmax(A &a, B b){if(a < b) {a = b; return 1;} return 0;} template <typename A, typename B> inline LL add(A x, B y) {if(x + y < 0) return x + y + mod; return x + y >= mod ? x + y - mod : x + y;} template <typename A, typename B> inline void add2(A &x, B y) {if(x + y < 0) x = x + y + mod; else x = (x + y >= mod ? x + y - mod : x + y);} LL mul(LL a, LL b, int mod = mod) { //a %= mod, b %= mod; return ((a * b - (LL)((LL)((long double)a / mod * b + 1e-3) * mod)) % mod + mod) % mod; } int fp(int a, int p, int mod = mod) { int base = 1; while(p) { if(p & 1) base = mul(base, a, mod); a = mul(a, a, mod); p >>= 1; } return base; } inline int read() { char c = getchar(); int x = 0, f = 1; while(c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();} while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar(); return x * f; } int N, K; int st, ans; vector<int> ds; unordered_map<LL, LL> t, vds; const int Tn = 9; int Cbase[11] = {2, 3, 5, 7, 11, 13, 17, 19, 23}; bool CheckP(int p) { if(p == 1) return 0; for(int i = 0; i < Tn; i++) if(p == Cbase[i]) return 1; for(int id = 0; id < Tn; id++) { int v = Cbase[id]; int lim = 0, t = p - 1, pre = 1; while(t && (!(t & 1))) lim++, t>>= 1; t = fp(v, t, p); while(lim--) { t = mul(t, t, p); if(t == 1 && (pre != p - 1 && pre != 1)) return 0; pre = t; } if(t != 1) return 0; } return 1; } int rnd() { return rand(); } int gcd(int a, int b) { return (!b) ? a : gcd(b, a % b); } int rd(int base, int mod) { return (mul(base, base, mod) + st) % mod; } int myabs(int x, int y) { return (x > y) ? x - y : y - x; } void Rho(int x) { if(x == 1) return ; if(CheckP(x)) { vds[x]++; return ; } while(1) { st = rand() % x + 1; int v1 = rnd() % x + 1, g = gcd(x, v1); if(g != 1 && g != x) {Rho(g); Rho(x / g); return ;} int v2 = v1; v1 = rd(v1, x); for(int k = 0, tr = 1; v1 - v2; v1 = rd(v1, x), k++) { g = gcd(x, myabs(v1, v2)); if(g != 1 && g != x) {Rho(g); Rho(x / g); return ;} if(k == tr) {v2 = v1; tr <<= 1;} } } } void Clear() { ds.clear(); vds.clear(); ans = 0; } int g(int x) { return fp(K, (x + 1) / 2); } int h(int x) { return (x & 1) ? x : x / 2; } void dfs(int n, int num, int cur, unordered_map<LL, LL>::iterator now) { if(now == vds.end()) { ds.pb(num); t[num] = cur; return ; } int nn = now->se, vv = now->fi, vvd = (1 - now->fi), nv = vv, nvd = vvd; auto nxt = ++now; dfs(n + 1, num, cur, nxt); for(int i = 1; i <= nn; i++) { dfs(n + 1, num * nv, cur * vvd, nxt); nv *= vv; nvd *= vvd; } } void print(int x) { if(x > 9) print(x / 10); putchar('0' + x % 10); } void solve() { Clear(); N = read(); K = read(); mod = read(); K %= mod; Rho(N); dfs(0, 1, 1, vds.begin()); for(auto &num: ds) { if((num & 1) && (!((N / num) & 1))) continue; add2(ans, mul(g(num), mul(h(num), t[N / num]))); } print(ans); putchar('\n'); } signed main() { #ifndef ONLINE_JUDGE freopen("a.in", "r", stdin); #endif srand(20020113); for(int T = read(); T--; solve()); return 0; }
我實在不想照着題解抄一遍公式了qwq
#include<bits/stdc++.h> #define Pair pair<int, int> #define MP make_pair #define fi first #define se second #define LL long long const int MAXN = 2e5 + 10, mod = 1e9 + 7; using namespace std; template <typename A, typename B> inline bool chmin(A &a, B b){if(a > b) {a = b; return 1;} return 0;} template <typename A, typename B> inline bool chmax(A &a, B b){if(a < b) {a = b; return 1;} return 0;} template <typename A, typename B> inline LL add(A x, B y) {if(x + y < 0) return x + y + mod; return x + y >= mod ? x + y - mod : x + y;} template <typename A, typename B> inline void add2(A &x, B y) {if(x + y < 0) x = x + y + mod; else x = (x + y >= mod ? x + y - mod : x + y);} template <typename A, typename B> inline LL mul(A x, B y) {return 1ll * x * y % mod;} template <typename A, typename B> inline void mul2(A &x, B y) {x = (1ll * x * y % mod + mod) % mod;} inline int read() { char c = getchar(); int x = 0, f = 1; while(c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();} while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar(); return x * f; } int mu[MAXN], prime[MAXN], vis[MAXN], tot, A, B, C, num, deg[MAXN]; int fa[MAXN], fb[MAXN], fc[MAXN]; vector<LL> di[MAXN]; vector<Pair> v[MAXN];//每一個數的質因數分解 struct Edge { LL u, v, w; }E[MAXN * 10]; void GetPrime(int N) { vis[1] = 1; mu[1] = 1; for(int i = 2; i <= N; i++) { if(!vis[i]) prime[++tot] = i, mu[i] = -1; for(int j = 1; j <= tot && i * prime[j] <= N; j++) { vis[i * prime[j]] = 1; if(i % prime[j]) mu[i * prime[j]] = -mu[i]; else {mu[i * prime[j]] = 0; break;} } } for(int i = 1; i <= tot; i++) for(int j = 1; j * prime[i] <= N; j++) di[j * prime[i]].push_back(prime[i]); } void Get(int *a, int N, int X) { for(int i = 1; i <= N; i++) for(int j = i; j <= N; j += i) a[i] += X / j; } LL lcm(int a, int b) { return 1ll * a / __gcd(a, b) * b; } void init() { memset(fa, 0, sizeof(fa)); memset(fb, 0, sizeof(fb)); memset(fc, 0, sizeof(fc)); memset(deg, 0, sizeof(deg)); num = 0; for(int i = 1; i <= A; i++) v[i].clear(); } void Build() { for(int w = 1; w <= A; w++) {//lcm(u, v) = w; if(!mu[w]) continue; int n = di[w].size(); //for(auto x : di[w]) printf("%d ", x); puts(""); for(int sta = 0; sta < (1 << n); sta++) { LL i = 1; for(int b = 0; b < n; b++) if(sta >> b & 1) i *= di[w][b]; for(int s = sta; ; s = sta & (s - 1)) {//tag LL g = 1; for(int b = 0; b < n; b++) if(s >> b & 1) g *= di[w][b]; int j = w * g / i; if(i < j) E[++num] = {i, j, w};// printf("%d\n", num); if(!s) break; } } } } LL fuck(int x, int y, int w) { if(mu[x] == 1) return add(add(mul(mul(fa[w], fb[w]), fc[y]), mul(mul(fa[w], fb[y]), fc[w])), mul(mul(fa[y], fb[w]), fc[w])); else return (-add(add(mul(mul(fa[w], fb[w]), fc[y]), mul(mul(fa[w], fb[y]), fc[w])), mul(mul(fa[y], fb[w]), fc[w])) + mod) % mod; } LL calc() { // for(int i = 1; i <= A; i++) for(auto &x : v[i])printf("%d %d %d\n", i, x.fi, x.se); for(int i = 1; i <= num; i++) { int x = E[i].u, y = E[i].v; if(deg[x] > deg[y]) swap(x, y); v[y].push_back(MP(x, E[i].w)); } LL ans = 0; for(int a = 1; a <= A; a++) { for(auto &t1 : v[a]) { LL b = t1.fi, w1 = t1.se; for(auto &t2 : v[b]) { LL c = t2.fi, w2 = t2.se, xi = mu[a] * mu[b] * mu[c]; LL w3 = lcm(a, c); if(w3 > A) continue; if(xi == 1) { add2(ans, mul(mul(fa[w1], fb[w2]), fc[w3])); add2(ans, mul(mul(fa[w1], fb[w3]), fc[w2])); add2(ans, mul(mul(fa[w2], fb[w1]), fc[w3])); add2(ans, mul(mul(fa[w2], fb[w3]), fc[w1])); add2(ans, mul(mul(fa[w3], fb[w1]), fc[w2])); add2(ans, mul(mul(fa[w3], fb[w2]), fc[w1])); } else if(xi == -1) { add2(ans, mul(mul(-fa[w1], fb[w2]), fc[w3])); add2(ans, mul(mul(-fa[w1], fb[w3]), fc[w2])); add2(ans, mul(mul(-fa[w2], fb[w1]), fc[w3])); add2(ans, mul(mul(-fa[w2], fb[w3]), fc[w1])); add2(ans, mul(mul(-fa[w3], fb[w1]), fc[w2])); add2(ans, mul(mul(-fa[w3], fb[w2]), fc[w1])); } // cout << ans << endl; } } } for(int i = 1; i <= num; i++) {//有兩個同樣 add2(ans, fuck(E[i].u, E[i].v, E[i].w)); add2(ans, fuck(E[i].v, E[i].u, E[i].w)); } for(int i = 1; i <= C; i++) {//全都同樣 if(mu[i] == 1) add2(ans, mul(mul(fa[i], fb[i]), fc[i])); else if(mu[i] == -1) add2(ans, -mul(mul(fa[i], fb[i]), fc[i]) + mod); } return ans; } void solve() { init(); A = read(); B = read(); C = read(); if(A < B) swap(A, B); if(C > B) swap(B, C); if(A < B) swap(A, B); Get(fa, A, A); Get(fb, A, B); Get(fc, A, C); Build(); cout << calc() << '\n'; } signed main() { GetPrime(2e5); for(int T = read(); T; T--, solve()); return 0; }
每一個位置\(x\)向\(\frac{x}{2}\)連邊最終會獲得一棵徹底二叉樹
題目轉化爲:給出一個有點權的樹,對於每一個點能夠花費\(b_i\)的代價使點權增長\(1\),問使得全部長度爲\(k + 1\)的鏈的點權和\(\% M\)均爲\(0\)的最小花費
首先考慮序列的狀況,稍加概括後不可貴到\(a_i \equiv a_{i + K + 1} \pmod M\)
放到樹上話那麼最終一個點的權值必定和它的\(K+1\)級祖先相同,所以對於前\(2^{k}\)個點,咱們\(O(nm)\)預處理出\(w[x][y]\)表示\(x\)的點爲\(y\)時,全部能被它限制的點的代價
如今只須要考慮前\(2^{k+1}-1\)個點,首先把標號\(< 2^k\)的葉子節點刪掉,對於剩下的點的限制條件變爲全部葉子節點到根的路徑和\(\% M =0\)。那麼設\(f[i][j]\)表示以\(i\)爲根的子樹,到全部葉子節點的權值\(\%M = j\)的最小代價,轉移的時候暴力枚舉該點的取值。
複雜度\(O(nm + 2^k m^2)\)能夠拿到70分
考慮\(w\)的預處理,std在這裏用了一個等差數列,實際上不用這麼麻煩,由於\(a[i]\)取值只有\(200\),直接對值域暴力就行
複雜度\(O(n + 2^k m^2)\)
#include<bits/stdc++.h> #define Pair pair<int, int> #define MP(x, y) make_pair(x, y) #define fi first #define se second //#define int long long #define LL long long #define pb push_back #define Fin(x) {freopen(#x".in","r",stdin);} #define Fout(x) {freopen(#x".out","w",stdout);} using namespace std; const int MAXN = 1e7 + 10, mod = 1e9 + 7; const LL INF = 1e18 + 10; const double eps = 1e-9; template <typename A, typename B> inline bool chmin(A &a, B b){if(a > b) {a = b; return 1;} return 0;} template <typename A, typename B> inline bool chmax(A &a, B b){if(a < b) {a = b; return 1;} return 0;} template <typename A, typename B> inline LL add(A x, B y) {if(x + y < 0) return x + y + mod; return x + y >= mod ? x + y - mod : x + y;} template <typename A, typename B> inline void add2(A &x, B y) {if(x + y < 0) x = x + y + mod; else x = (x + y >= mod ? x + y - mod : x + y);} template <typename A, typename B> inline LL mul(A x, B y) {return 1ll * x * y % mod;} template <typename A, typename B> inline void mul2(A &x, B y) {x = (1ll * x * y % mod + mod) % mod;} template <typename A> inline void debug(A a){cout << a << '\n';} template <typename A> inline LL sqr(A x){return 1ll * x * x;} inline int read() { char c = getchar(); int x = 0, f = 1; while(c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();} while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar(); return x * f; } int ch(int x, int l, int r) { return x >= l && x <= r; } int N, K, M, P, a[MAXN], mx[MAXN], n, jump, fa[MAXN], b[MAXN]; vector<int> bel[MAXN]; unsigned int SA, SB, SC;int p, A, B; unsigned int rng61(){ SA ^= SA << 16; SA ^= SA >> 5; SA ^= SA << 1; unsigned int t = SA; SA = SB; SB = SC; SC ^= t ^ SA; return SC; } void gen(){ N = read(); K = read(); M = read(); P = read(); SA = read(); SB = read(); SC = read(); A = read(); B = read(); for(int i = 1; i <= P; i++) a[i] = read() % M, b[i] = read(); for(int i = P + 1; i <= N; i++){ a[i] = rng61() % A + 1; a[i] %= M; b[i] = rng61() % B + 1; } } LL w[(1 << 12) - 1][201];//w[i][j] 當i爲j時,全部受i限制的點的代價 LL f[(1 << 12) - 1][201], num[211]; void dfs(int x, int dep) { mx[x] = dep; if(dep > K + 1) bel[fa[x]].pb(x); int base = 2 * x; for(int i = 0; i <= 1; i++) { int to = 2 * x + i; if(to > N) continue; dfs(to, dep + 1); chmax(mx[x], mx[to]); } } LL get(int val, LL target, LL inc) {//在%M意義下把val變爲target的最小花費 if(target >= val) return 1l * (target - val) * inc; return 1ll * ((M - val) + target) * inc; } void dfs2(int x) { if(x > n || mx[x] <= K) return ; if(x >= (1 << K)) {//葉節點 for(int i = 0; i < M; i++) f[x][i] = w[x][i]; return ; } for(int i = 0; i < 2; i++) if(2 * x + i <= n) dfs2(2 * x + i); for(int i = 0; i < M; i++) {//與葉子節點的路徑和%M = j f[x][i] = INF; for(int j = 0; j < M; j++) {//該節點的增量 LL sv = 0; for(int gg = 0; gg < 2; gg++) { int to = 2 * x + gg; if(to <= n) sv += f[to][(i - a[x] - j + 2 * M) % M]; } chmin(f[x][i], sv + w[x][(a[x] + j) % M]); } } } void solve() { gen(); memset(f, 0, sizeof(f)); memset(w, 0, sizeof(w)); jump = 1; n = (1 << (K + 1)) - 1; for(int i = 1; i <= K + 1; i++) jump *= 2; for(int i = 1; i <= N; i++) { bel[i].clear(); } for(int i = 1; i <= N; i++) fa[i] = (i <= n ? i : fa[i / jump]); dfs(1, 1); for(int i = 1; i < (1 << (K + 1)); i++) { memset(num, 0, sizeof(num)); for(auto &son: bel[i]) num[a[son]] += b[son]; for(int j = 0; j < M; j++) { w[i][j] += get(a[i], j, b[i]); for(int k = 0; k < M; k++) w[i][j] += get(k, j, num[k]); } } dfs2(1); cout << f[1][0] << '\n'; } signed main() { #ifndef ONLINE_JUDGE freopen("title-task3.in", "r", stdin); #endif for(int T = read(); T--; solve()); return 0; }