2019 ICPC Asia Yinchuan Regional


Contest Info


[Practice Link](https://www.jisuanke.com/contest/5527?view=challenges)
Solved A B C D E F G H I J K L M N
9/14 O O - O - O O O O - O - - O
  • O 在比賽中通過
  • Ø 賽后通過
  • ! 嘗試了但是失敗了
  • - 沒有嘗試

Solutions


A. Girls Band Party

題意:

給出一個\(n\),然后給出\(n\)個名字、顏色、分數,然后給出\(5\)個獎勵名字和一個獎勵顏色,從\(n\)個中選擇\(5\)個,選出的\(5\)個名字不重復,如果出現一個獎勵名字,則獲得\(10\%\)的總評分數,出現一個獎勵顏色,則獲得\(20\%\)的總評分數,求最大的總評分數

思路:

先將每個名字分為獎勵顏色和非獎勵顏色兩種,分別取\(max\),然后枚舉每個獎勵名字的不選、選擇獎勵顏色、選擇非獎勵顏色三種情況,然后對於剩下需要選擇的名字,從非獎勵顏色中取前\(10\)個二進制枚舉進行選擇,剩下的從獎勵顏色中選擇

代碼:

view code
#include <bits/stdc++.h>

using namespace std;
#define dbg(x...) do { cout << "\033[32;1m" << #x << " -> "; err(x); } while (0)
void err() { cout << "\033[39;0m" << endl; }
template <class T, class... Ts>
void err(const T& arg, const Ts&... args) { cout << arg << ' '; err(args...); }

const int N = 1e5 + 10;

struct node {
	string name;
	string col;
	int val;

}a[N];

struct qnode {
	int id;
	int val;

	qnode() {}

	qnode(int id, int val): id(id), val(val) {}

	bool operator < (const qnode &other) const {
		return val > other.val;
	}
};

int res;
int n, tot;
string name[10], col;
int bor[10][2];
int b[N][2];
map<string, int>mp;
vector<qnode> vec[2];
int vis[N];

int getId(const string &t) {
	if (mp.count(t)) return mp[t];
	mp[t] = ++tot;
	return mp[t];
}

void gao(int pos, int match_name, int match_col, int sum) {
	if (pos > 5) {
		int limit = min(10, (int)vec[0].size()), sub = 5 - match_name;
		for (int S = 0; S < (1 << limit); ++S) {
			int tmp = sum;
			int match = match_col;
			int need = sub;
			for (int i = 0; i < limit; ++i) {
				if (S & (1 << i)) {
					vis[vec[0][i].id] = 1;
					tmp += vec[0][i].val;
					need--;
				} 
			}
			if (need > 0) {
				for (auto &it : vec[1]) {
					if (!vis[it.id]) {
						need--;
						tmp += it.val;
						match++;
						if (need == 0) break;
					}
				}
			}
			if (need == 0) {
				double other = 0.1 * match_name + 0.2 * match;
				tmp = tmp * (1.0 + other);
				res = max(res, tmp);
			}
			for (int i = 0; i < limit; ++i) {
				vis[vec[0][i].id] = 0;
			}
		}
		return ;
	} else {
		gao(pos + 1, match_name, match_col, sum);
		if (bor[pos][0])
			gao(pos + 1, match_name + 1, match_col, sum + bor[pos][0]);
		if (bor[pos][1])
			gao(pos + 1, match_name + 1, match_col + 1, sum + bor[pos][1]);
	}
}

int main() {
	ios::sync_with_stdio(false);
	cin.tie(0), cout.tie(0);
	int T;
	cin >> T;
	while (T--) {
		cin >> n;
		
		res = 0;
		memset(bor, 0, sizeof bor);
		tot = 0;
		mp.clear();
		vec[0].clear(), vec[1].clear();
		memset(b, 0, sizeof b);

		for (int i = 1; i <= n; ++i) {
			cin >> a[i].name >> a[i].col >> a[i].val;
		}
		for (int i = 1; i <= 5; ++i) {
			cin >> name[i];
		}
		cin >> col;
		for (int i = 1; i <= 5; ++i) getId(name[i]);
		for (int i = 1; i <= n; ++i) {
			int id = getId(a[i].name);
			if (id <= 5) {
				if (a[i].col == col) {
					bor[id][1] = max(bor[id][1], a[i].val);
				} else {
					bor[id][0] = max(bor[id][0], a[i].val);
				}
			} else {
				if (a[i].col == col) {
					b[id][1] = max(b[id][1], a[i].val);
				} else {
					b[id][0] = max(b[id][0], a[i].val);
				}
			}
		}
		for (int i = 6; i <= tot; ++i) {
			for (int j = 0; j < 2; ++j) {
				if (b[i][j])
					vec[j].push_back(qnode(i, b[i][j]));
			}	
		}
		sort(vec[0].begin(), vec[0].end());
		sort(vec[1].begin(), vec[1].end());
		gao(1, 0, 0, 0);
		printf("%d\n", res);
	}
	return 0;
}

B. So Easy

題意:
給出一個\(n \cdot n\)的矩形,這個矩形\(a_{i, j}\)的初始值為\(0\),它每次能夠選擇一行或者一列加上\(1\),現在遮住某個位置的數,讓你還原這個數。

思路:
考慮倒退操作,不考慮遮住的那個數,然后枚舉每行,每列,每次選擇行最小,列最小將整行整列減去即可還原出那個數。

代碼:

view code
#include <bits/stdc++.h>
using namespace std;
const int N = 1e3 + 10;
int n, a[N][N];

int main() {
	while (scanf("%d", &n) != EOF) {
		int x = -1, y = -1;
		for (int i = 1; i <= n; ++i) {
			for (int j = 1; j <= n; ++j) {
				scanf("%d", &a[i][j]);
				if (a[i][j] == -1) {
					x = i, y = j;
					a[i][j] = 0;
				}
			}
		}
		for (int i = 1; i <= n; ++i) {
			int Min = 1e9;
			for (int j = 1; j <= n; ++j) {
				if (x == i && y == j) continue;
				Min = min(Min, a[i][j]);
			}
			for (int j = 1; j <= n; ++j) {
				a[i][j] -= Min;
			}
		}
		for (int j = 1; j <= n; ++j) {
			int Min = 1e9;
			for (int i = 1; i <= n; ++i) {
				if (x == i && y == j) continue;
				Min = min(Min, a[i][j]);
			}
			for (int i = 1; i <= n; ++i) {
				a[i][j] -= Min;
			}
		}
		printf("%d\n", -a[x][y]);
	}
	return 0;
}

D. Easy Problem

題意:
定義一個序列\((a_1, a_2, \cdots, a_n)\)是一個\((n, m, d)-good\)當且僅當\(1 \leq a_i \leq m(1 \leq i \leq n)\)並且\(gcd(a_1, a_2, \cdots, a_n) = d\)
\(f(a, k) = (a_1a_2\cdots a_n)^k\),現在給出\(n, m, d, k\),讓你求所有合法的\((n, m, d)-good\)的序列\(a\)\(f(a, k)\)

思路:
題目要求的東西等價於:

\[\begin{eqnarray*} f(d) = \sum\limits_{a_1 = 1}^m \sum\limits_{a_2 = 1}^m \cdots \sum\limits_{a_n = 1}^m [gcd(a_1, a_2, \cdots, a_n) = d](a_1a_2\cdots a_n)^k \end{eqnarray*} \]

那么我們令:

\[\begin{eqnarray*} g(d) = \sum\limits_{a_1 = 1}^m \sum\limits_{a_2 = 1}^m \cdots \sum\limits_{a_n = 1}^m [d | gcd(a_1, a_2, \cdots, a_n)](a_1a_2\cdots a_n)^k \end{eqnarray*} \]

顯然有:

\[\begin{eqnarray*} g(d) = (\sum\limits_{d\;|\;i} i^k)^n \end{eqnarray*} \]

莫比烏斯反演有:

\[\begin{eqnarray*} f(d) &=& \sum\limits_{d\;|\;i} \mu(\frac{i}{d})g(i) \\ &=& \sum\limits_{d\;|\;i} \mu(\frac{i}{d}) (\sum\limits_{i\;|\;j} j^k)^n \end{eqnarray*} \]

所以:

\[f(d) = \sum\limits_{i = 1}^{\left\lfloor m/d \right\rfloor} \mu(i) (\sum\limits_{id\;|\;j} j^k)^n \]

代碼:

view code
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const int N = 1e5 + 10, mod = 59964251;
int pri[N], check[N], mu[N], n, m, d, K, phi; 
char s[N]; 
void sieve() {
	memset(check, 0, sizeof check);
	*pri = 0;
	mu[1] = 1;
	for (int i = 2; i < N; ++i) {
		if (check[i] == 0) {
			pri[++*pri] = i;
			mu[i] = -1;
		}
		for (int j = 1; j <= *pri; ++j) {
			if (i * pri[j] >= N) break;
			check[i * pri[j]] = 1;
			if (i % pri[j] == 0) {
				mu[i * pri[j]] = 0;
				break;
			} else {
				mu[i * pri[j]] = -mu[i];
			}
		}
	}
}

int eular(int n) {
	int ans = n;
	for (int i = 2; i * i <= n; ++i) {
		if (n % i == 0) {
			ans -= ans / i;
			while (n % i == 0) 
				n /= i;
		}
	}
	if (n > 1) ans -= ans / n;
	return ans;
}

ll gcd(ll a, ll b) {
	return b ? gcd(b, a % b) : a;
}

ll qmod(ll base, ll n) {
	ll res = 1;
	while (n) {
		if (n & 1) res = res * base % mod;
		base = base * base % mod;
		n >>= 1;
	}
	return res;
}

int getMod(int mod) {
	int res = 0;
	for (int i = 1; s[i]; ++i) {
		res = (res * 10 + s[i] - '0') % mod;
	}
	return res;
}

int main() {
	phi = eular(mod);
	sieve(); 	
//	cout << phi << endl;
	int _T; scanf("%d", &_T);
	while (_T--) {
		scanf("%s%d%d%d", s + 1, &m, &d, &K);
		int len = strlen(s + 1);
		if (len <= 9) {
			n = 0;
			for (int i = 1; s[i]; ++i) {
				n = n * 10 + s[i] - '0';
			}
		} else {
			n = getMod(phi);
			if (getMod(643) == 0 || getMod(93257) == 0) {
				n += phi;
			}
		}
		ll res = 0;
		for (int i = 1; i <= m / d; ++i) {
			int base = 0;
			for (int j = i * d; j <= m; j += i * d) {
				base += qmod(j, K);
				base %= mod;
			}
			res += 1ll * mu[i] * qmod(base, n) % mod;
			res = (res + mod) % mod;
		}
		printf("%lld\n", res);
	}
	return 0;
}

E. XOR Tree

題意:
定義一個multiset的權值為里面任意兩個數的異或和的平方的和。
現在給出一棵有根樹(\(1\)為根),每個點有點權,定義\(p(x, k)\)\(x\)子樹中距離\(x\)不超過\(k\)的所有點的點權構成的multiset的權值,現在要對每個\(i \in [1, n]\)\(p(i, k)\)

F. Function!

G. Pot!!

裸的線段樹。

代碼:

view code
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
int n, q;
struct SEG {
	struct node {
		int Max, lazy;
		node() { Max = lazy = 0; }
		void up(int x) {
			Max += x;
			lazy += x;
		}
		node operator + (const node &other) const {
			node res = node();
			res.Max = max(Max, other.Max);
			return res;
		}
	}t[N << 2];
	void build(int id, int l, int r) {
		t[id] = node();
		if (l == r) return;
		int mid = (l + r) >> 1;
		build(id << 1, l, mid);
		build(id << 1 | 1, mid + 1, r);
	}
	void down(int id) {
		int &lazy = t[id].lazy;
		if (lazy) {
			t[id << 1].up(lazy);
			t[id << 1 | 1].up(lazy);
			lazy = 0;
		}
	}
	void update(int id, int l, int r, int ql, int qr, int v) {
		if (l >= ql && r <= qr) {
			t[id].up(v);
			return;
		}
		int mid = (l + r) >> 1;
		down(id);
		if (ql <= mid) update(id << 1, l, mid, ql, qr, v);
		if (qr > mid) update(id << 1 | 1, mid + 1, r, ql, qr, v);
		t[id] = t[id << 1] + t[id << 1 | 1];
	}
	int query(int id, int l, int r, int ql, int qr) {
		if (l >= ql && r <= qr) return t[id].Max;
		int mid = (l + r) >> 1;
		down(id);
		int res = 0;
		if (ql <= mid) res = max(res, query(id << 1, l, mid, ql, qr));
		if (qr > mid) res = max(res, query(id << 1 | 1, mid + 1, r, ql, qr));
		return res;
	}
}seg[4];

int main() {
	int id[] = {0, 0, 0, 1, 0, 2, 0, 3, 0};
	vector <vector<int>> vec;
	vec.resize(15);
	for (int i = 2; i <= 10; ++i) {
		int x = i;
		vec[i].clear();
		for (int j = 2; j <= x; ++j) {
			while (x % j == 0) {
				vec[i].push_back(j);
				x /= j;
			}
		}
	//	cout << i << endl;
	//	for (auto &it : vec[i])
	//		cout << it << " ";
	//	cout << endl;
	}
	while (scanf("%d%d", &n, &q) != EOF) {
		for (int i = 0; i < 4; ++i) seg[i].build(1, 1, n);
		char op[20]; int l, r, x;
		while (q--) {
			scanf("%s%d%d", op, &l, &r);
			if (op[1] == 'U') {
				scanf("%d", &x);
				for (auto &it : vec[x]) {
					seg[id[it]].update(1, 1, n, l, r, 1);
				}
			} else {
				int res = 0;
				for (int i = 0; i < 4; ++i) {
					res = max(res, seg[i].query(1, 1, n, l, r));
				}
				printf("ANSWER %d\n", res);
			}
		}	
	}
	return 0;
}

H. Delivery Route

題意:
給出一張圖,有\(x\)條無向邊,有\(y\)條有向邊,保證無向邊都是正權值,有向邊可能有負權值,並且保證如果一條有向邊\(a_i \rightarrow b_i\),那么在該圖中,\(b_i\)不可能到達\(a_i\)
現在詢問從\(s\)出發到任意一點的最短路。

思路:
我們考慮如果只考慮有向邊,那么是一個\(DAG\),那么把無向邊連成的每個聯通塊看成一個新點,並且有有向邊將他們連接起來,他們也是一個\(DAG\)
並且無向圖的連通塊里面沒有負權邊,可以跑dijkstra,然后根據拓撲序dp一下即可。

代碼:

view code
#include <bits/stdc++.h>
using namespace std;
using pII = pair<int, int>;
#define dbg(x...) do { cout << "\033[32;1m" << #x << " -> "; err(x); } while (0)
void err() { cout << "\033[39;0m" << endl; }
template <class T, class... Ts>
void err(const T& arg, const Ts&... args) { cout << arg << ' '; err(args...); }
#define fi first
#define se second
const int N = 5e4 + 10, INF = 0x3f3f3f3f;
int n, mx, my, s, id[N], d[N];
//0 two-way 1 one-way
vector <vector<pII>> G[3];
vector <vector<int>> po;
struct DSU {
	int fa[N];
	void init() { memset(fa, 0, sizeof fa); }
	int find(int x) {
		return fa[x] == 0 ? x : fa[x] = find(fa[x]);
	}
	void merge(int u, int v) {
		int fu = find(u), fv = find(v);
		if (fu != fv) {
			fa[fu] = fv;
		}
	}
}dsu;

struct node {
	int u, w;
	node() {}
	node(int u, int w) : u(u), w(w) {}
	bool operator < (const node &other) const {
		return w > other.w;
	}
};
int dis[N], used[N];
void Dijkstra(int S) {
	priority_queue <node> pq;
	pq.push(node(S, dis[S]));
	while (!pq.empty()) {
		int u = pq.top().u; pq.pop();
		for (auto &it : G[0][u]) { 
			int v = it.fi, w = it.se;
			if (dis[v] > dis[u] + w) {
				dis[v] = dis[u] + w;
				pq.push(node(v, dis[v]));
			}	
		}
	}
}

void Topo() {
	queue <int> que;
	for (int i = 1; i <= *id; ++i) {
		if (d[i] == 0) {
			que.push(i);
		}
	}	
	while (!que.empty()) {
		int u = que.front(); que.pop();
		sort(po[u].begin(), po[u].end(), [&](int a, int b) { return dis[a] < dis[b]; });
		for (auto &it : po[u]) {
			Dijkstra(it);
			for (auto &it2 : G[1][it]) {
				int v = it2.fi, w = it2.se;
				if (dis[it] < INF) {
					dis[v] = min(dis[v], dis[it] + w);
				}
			}
		}	
		for (auto &it : G[2][u]) {
			int v = it.fi;
			if (--d[v] == 0) {
				que.push(v);
			}
		}
	}
}

int main() {
	while (scanf("%d%d%d%d", &n, &mx, &my, &s) != EOF) {
		for (int i = 1; i <= n; ++i) {
			dis[i] = INF;
		}
		dis[s] = 0;
		*id = 0;
		G[0].clear(); G[1].clear();
		G[0].resize(n + 1); G[1].resize(n + 1);
		for (int i = 1, u, v, w; i <= mx; ++i) {
			scanf("%d%d%d", &u, &v, &w);
			G[0][u].push_back(pII(v, w));
			G[0][v].push_back(pII(u, w));
		}
		for (int i = 1, u, v, w; i <= my; ++i) {
			scanf("%d%d%d", &u, &v, &w);
			G[1][u].push_back(pII(v, w));
		}
		dsu.init();
		for (int u = 1; u <= n; ++u) {
			for (auto &it : G[0][u]) {
				int v = it.fi;
				dsu.merge(u, v);
			}
		}
		for (int u = 1; u <= n; ++u) {
			if (dsu.fa[u] == 0)
				id[u] = ++*id;
		}
		for (int u = 1; u <= n; ++u) {
			if (dsu.fa[u]) {
				id[u] = id[dsu.find(u)];
			}
		}
	//	for (int i = 1; i <= n; ++i)
	//		dbg(i, id[i]); 
		po.clear(); po.resize(*id + 10);
		G[2].clear(); G[2].resize(*id + 10);
		memset(d, 0, sizeof d);
		for (int u = 1; u <= n; ++u) {
		    po[id[u]].push_back(u);	
			for (auto &it : G[1][u]) { 
				int v = it.fi;
				if (id[u] != id[v]) {
					G[2][id[u]].push_back(pII(id[v], v));
					++d[id[v]];
				}
			}
		}
		Topo();
		for (int i = 1; i <= n; ++i) {
			if (dis[i] >= INF) puts("NO PATH");
			else printf("%d\n", dis[i]);
		}
		
	}
	return 0;
}

I. Base62

題意:
進制轉換

代碼:

view code

def main():
    l = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L',
         'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h',
         'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z']
    x, y, z = input().split()
    x = int(x)
    y = int(y)
    num = 0
    for c in z:
        if ord('0') <= ord(c) <= ord('9'):
            num = num * x + ord(c) - ord('0')
        elif ord('A') <= ord(c) <= ord('Z'):
            num = num * x + ord(c) - ord('A') + 10
        else:
            num = num * x + ord(c) - ord('a') + 36
    if num == 0:
        print("0")
        return 
    res = ""
    while num > 0:
        tmp = num % y
        res = res + l[tmp]
        num = num // y
    # print(res)
    res = res[::-1]
    print(res)

main()

K. Largest Common Submatrix

題意:
給出兩個\(n \cdot m\)的矩形,並且里面的數是\([1, nm]\)的排列。
求兩個矩形的最大公共子矩形,這里的大定義為面積。

思路:
考慮里面的數是一個排列,可以\(O(n^2)\)處理出每個數向上拓展多少,向左右拓展多少,然后考慮每一行,肯定是某段連續的長度然后乘上這段最小的向上拓展的數量。
向上拓展的這部分當成一個維,位置當成一維,丟進笛卡爾樹里面跑一跑能跑出每個最小值管轄的范圍,然后和左右擴展的范圍求交,就是每個向上拓展數量在橫向最遠能擴展的范圍。

代碼:

view code
#include <bits/stdc++.h>
using namespace std;
using pII = pair<int, int>; 
#define dbg(x...) do { cout << "\033[32;1m" << #x << " -> "; err(x); } while (0)
void err() { cout << "\033[39;0m" << endl; }
template <class T, class... Ts>
void err(const T& arg, const Ts&... args) { cout << arg << ' '; err(args...); }
#define fi first
#define se second
const int N = 1e3 + 10, INF = 0x3f3f3f3f;
int n, m, a[N][N], b[N][N], l[N][N], r[N][N], num[N][N];
pII c[N], id[N * N];

struct CT {
	struct node {
		int id, val, fa;
		int son[2];
		node() {}
		node (int id, int val, int fa) : id(id), val(val), fa(fa) {
			son[0] = son[1] = 0;
		}
		bool operator < (const node &other) const {
			return val < other.val;
		}
	}t[N];
	int root;
	void init() {
		t[0] = node(0, -INF, 0);
	}
	void build(int n, int *a) {
		for (int i = 1; i <= n; ++i) {
			t[i] = node(i, a[i], 0);
		}
		for (int i = 1; i <= n; ++i) {
			int k = i - 1;
			while (t[i] < t[k]) {
				k = t[k].fa;
			}
			t[i].son[0] = t[k].son[1];
			t[k].son[1] = i;
			t[i].fa = k;
			t[t[i].son[0]].fa = i;
		}
		root = t[0].son[1];
	}
	int dfs(int u) {
		if (!u) return 0;
		c[u].fi = dfs(t[u].son[0]);
		c[u].se = dfs(t[u].son[1]);
		return c[u].fi + c[u].se + 1;
	}
}ct;

int main() {
	while (scanf("%d%d", &n, &m) != EOF) {
		for (int i = 1; i <= n; ++i) {
			for (int j = 1; j <= m; ++j) {
				scanf("%d", &a[i][j]);
			}
		}
		for (int i = 1; i <= n; ++i) {
			for (int j = 1; j <= m; ++j) {
				scanf("%d", &b[i][j]);
				id[b[i][j]] = pII(i, j); 
			}
		}

		for (int i = 1; i <= n; ++i) {
			for (int j = 1; j <= m; ++j) {
				if (j == 1) {
					l[i][j] = j;
				} else {
					int pre = a[i][j - 1], now = a[i][j];
					if (id[pre].fi == id[now].fi && id[pre].se == id[now].se - 1) {
						l[i][j] = l[i][j - 1];
					} else {
						l[i][j] = j;
					}
				}
			}
			for (int j = m; j >= 1; --j) {
				if (j == m) {
					r[i][j] = j;
				} else {
					int nx = a[i][j + 1], now = a[i][j];
					if (id[nx].fi == id[now].fi && id[nx].se == id[now].se + 1) {
						r[i][j] = r[i][j + 1];
					} else {
						r[i][j] = j;
					}
				}
			}
		}
		for (int j = 1; j <= m; ++j) {
			for (int i = 1; i <= n; ++i) {
				if (i == 1) {
					num[i][j] = 1;
				} else {
					int pre = a[i - 1][j], now = a[i][j];
					if (id[pre].fi == id[now].fi - 1 && id[pre].se == id[now].se) {
						num[i][j] = num[i - 1][j] + 1;
					} else {
						num[i][j] = 1;
					}
				}
			}
		}
		int res = 0;
		for (int i = 1; i <= n; ++i) {
		//	for (int j = 1; j <= m; ++j) {
		//		dbg(i, j, l[i][j], r[i][j], num[i][j]);
		//	}
			ct.init();
			ct.build(n, num[i]);
			ct.dfs(ct.root);
			for (int j = 1; j <= m; ++j) {
				int tl = max(l[i][j], j - c[j].fi);
				int tr = min(r[i][j], j + c[j].se);
				res = max(res, (tr - tl + 1) * num[i][j]);
			}
		}
		printf("%d\n", res);
	}
	return 0;
}

N. Fibonacci Sequence

純輸出題


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM