1. 程式人生 > 實用技巧 >8.2集訓

8.2集訓

上午

考試

下午

第一題

一句話題意:給出兩個\(1\) \(to\) \(n\)的序列,定義\(T(a,b)\)\(a\)\(b\)在序列中的距離

其計算公式為:\(下標_{b所在的位置} - 下標_{a所在的位置}\)

找出兩個序列中,\(max({T_1(a,b),+T_2(a,b))}\)

看一組例子:

A:3 2 1 4 5
B:2 5 1 3 4

考慮\(2\)\(4\)這兩個數字對答案的貢獻,

顯然:\(ans_{當前} = (下標_{4所在的A系列位置}-下標_{2所在的A序列位置}) +(下標_{4所在的B系列位置}-下標_{2所在的B序列位置})\)

合併之後得到:\(ans_{當前} = (下標_{4所在的A系列位置} + 下標_{4所在的B系列位置})-(下標_{2所在的A序列位置} + 下標_{2所在的B序列位置})\)

A序列中的\(2\)\(4\)是遞增分佈的,考慮,如果B序列中出現\(4.......2\)的情況怎麼辦?

或者A序列中\(4.......2\),而B序列中\(2......4\)怎麼辦?

也就是說B序列與A序列的“順序不同”(需要感性理解)

這時候我們考慮把下標從右往左標上一圈,原來不是從左往右嗎?現在所謂的“逆序”,我們從右往左,實現也很簡單,\(n-下標_{當前}+1\)就是你逆序之後的下標

給出自己的程式碼(借鑑了Tethysdalao的程式碼)

#include <bits/stdc++.h>
#define LL long long
#define debug
using namespace std;

inline long long read() {
	long long s = 0, f = 1; char ch;
	while(!isdigit(ch = getchar())) (ch == '-') && (f = -f);
	for(s = ch ^ 48;isdigit(ch = getchar()); s = (s << 1) + (s << 3) + (ch ^ 48));
	return s * f;
}

const int N = 1e6+66;

int n, res, ans_s_max, ans_s_min = N<<1, ans_n_max, ans_n_min = N<<1;
int a[N], b[N], f[N];

inline void shuruyijijiejueheshuchu() {
	n = read();
	for (int i = 1; i <= n; ++ i) a[i] = read();
	for (int i = 1; i <= n; ++ i) {
		b[i] = read();
		f[b[i]] = i;
	}
	for (int i = 1; i <= n; ++ i) {
		ans_s_max = max(ans_s_max, i + f[a[i]]);
		ans_s_min = min(ans_s_min, i + f[a[i]]);
		ans_n_max = max(ans_n_max, i + n-f[a[i]]+1);
		ans_n_min = min(ans_n_min, i + n-f[a[i]]+1);
		res = max(res, ans_s_max - ans_s_min);
		res = max(res, ans_n_max - ans_n_min);
	}
	cout << res;
}

inline int thestars() {
	freopen ("distance.in", "r", stdin);
	freopen ("distance.out", "w", stdout);
	shuruyijijiejueheshuchu();
	fclose (stdin), fclose (stdout);
	return 0;
}

int youngore = thestars();

signed main() {;}
/*
5
2 1 5 3 4
4 2 5 1 3
*/

我懶得去寫具體的程式碼分析了,日後補吧

第二題

一句話題意:求\(\begin{aligned}\sum_{i=0}^xC_{x}^i*C_{y}^{z+i}\%998244353\end{aligned}\)

其中資料:\(T<=10000,0<=x,y,z<=1000000\)

可曾聽聞範德蒙德卷積?

然後就沒了

\(\begin{aligned}\sum_{i=0}^k{C_n^iC_{m}^{k-i}}=C_{n+m}^{k}\end{aligned}\)

具體詳見Ame__

給出程式碼:

#include <bits/stdc++.h>
#define int long long
#define debug
using namespace std;

const int N = 1e7+66, mod = 998244353;

inline int read() {
	int s = 0, f = 1; char ch;
	while(!isdigit(ch = getchar())) (ch == '-') && (f = -f);
	for(s = ch ^ 48;isdigit(ch = getchar()); s = (s << 1) + (s << 3) + (ch ^ 48));
	return s * f;
}

int x, y, z, t;
int js[N];
inline int ksm(int a , int b){
    int res = 1;
    for(; b ; b >>= 1 , a = a * a % mod){
        if(b & 1){
            res = res * a % mod;
        }
    }
    return res % mod;
}

inline int C(int n, int m) {
	if (n < m) return 0;
	return js[n]*ksm(js[m]*js[n-m]%mod, mod-2)%mod;
}

inline int Lucas(int n, int m) {
	if (!m) return 1;
	return C(n%mod, m%mod)*Lucas(n/mod, m/mod)%mod;
}

inline void shuruhejiejueheshuchu() {
	t = read();
	// cin >> t;
	js[0] = 1, js[1] = 1;
	for (int i = 2; i <= N; ++ i) js[i] = js[i - 1]*i%mod;
	while (t -- > 0) {
		// cin >> x >> y >> z;
		x = read(), y = read(), z = read();
		int sum =  Lucas(x+y, x+z)%mod;
		cout << sum << '\n';
	}
}

inline int thestars() {
	freopen ("number.in", "r", stdin);freopen ("number.out", "w", stdout);
	shuruhejiejueheshuchu();
	fclose (stdin), fclose (stdout);
	return 0;
}

int youngore = thestars();

signed main() {;}

這題tmd卡快讀,艹,我用\(cin\)全T飛了

第三題

一句話題意:給你個序列,每次要異或一個數,還要查詢一個判定器,其中\(n \leq 1e6\)

顯然暴力\(n^2\),正解是:\(01Tire\),艹,我就是tm講的Trie樹,我自己沒看出來,老往主席樹什麼玩意的想去了

關鍵是前幾天學長好幾道異或的題,都跟01Trie樹沒關係啊,我知道是01Trie樹之後,當場mmp

後來gzh奆佬直言:學過01Trie樹的一眼就能看出來(於是口吐不清的開始了他迷迷糊糊的講解)

我:我\(*\)你ma,你個\(**\)玩意….@#¥%……&*!

簡直SB一枚…..

以前見過一句話,碰到傻逼怎麼辦?別跟他爭論,順著他的話走,把他培養成一個大SB

有道理!

具體思路:在01Trie樹上搞一搞就可以了

給出程式碼:

#include <bits/stdc++.h>
#define LL long long
#define debug
using namespace std;

const int N = 6e6+66;

int n, t, x, y, cnt;
int ch[N][6], tag[N];

inline void shuruyijijiejueheshuchu() {
	cin >> n >> t;
	for (int i = 1; i <= n; ++ i) {
		int now = 0;
		cin >> x;
		for (int j = 16; j >= 0; -- j) {
			if (!ch[now][x>>j&1]) ch[now][x>>j&1] = ++ cnt;
			now = ch[now][x>>j&1];
			++ tag[now];
		}
	}
	while (t --> 0) {
		int res = 0, now = 0;
		cin >> x >> y;
		for (int j = 16; j >= 0; -- j) {
			if (y>>j&1) res += tag[ch[now][x>>j&1]];
			now = ch[now][(y>>j&1)^(x>>j&1)];
			if (!now) break;
		}
		if (now) res += tag[now];
		cout << res << '\n';
	}
}

inline int thestars() {
	freopen ("phone.in", "r", stdin);
	freopen ("phone.out", "w", stdout);
	shuruyijijiejueheshuchu();
	fclose (stdin), fclose (stdout);
	return 0;
}

int youngore = thestars();

signed main() {;}
/*
5 5
7 6 7 3 4
2 6
1 8
8 7
3 2
6 2
*/