2022.9.19———HZOI【CSP-S模拟6】游寄

Preface

试验一下难度。———Au爷沈队(学长)

这句话,我理解为“铈囐镒䪗䁪鑟”

Rank24/43

80pts+9pts+0pts+0pts=89pts

T1 玩水, T2 AVL树, T3 暴雨, T4 置换

T1 

这个是场切题,找找规律就好了。

设这样一个点是“美丽点”:

x y
y z

x即为我所说的“美丽点”。

这只是我给他起了个名字((

考虑这个点的实际意义。这意味着在x位置有一个人可以和大部队分开,然后再在z点集合,这样就导致有一个人的路线和大部队的路线不相同,而走过的字符串是相同的。

那么找到两个这样的美丽点就行,这样3个人的路线就都不相同了。

但是会发现有不合法的情况出现。

由于题目限制只能往下或者往右走,所以当这种情况发生是不合法的:

x y b d
y z d h
e f
f g

可以看到xbe都是美丽点。但是从x点走到z点,就去不了b点或者e点了;从e点走到g点,也就去不了x点和b点了;从b点走到h点同理,也就去不了x点或e点了。

因此这样是不合法的。即xy坐标相同的美丽点不能同时作为答案(特殊情况除外 (特殊情况就是这个下面我要说的这个) )

还有一种特殊的合法情况:

x y b
y b c

可以看到坐标为(1,1)(1,2)的两个点都是美丽点。我们显然一个人从x分开走下边的y,大部队走到上面的y后再让一个人分开走下边的b,最终三人在c点回合,发现字符串仍然是相同的,并且方案满足不同。

竖着的话同理。

也就是说,对于一个美丽点(x,y),除了点(x+1,y)(x,y+1)之外,其他x坐标或y坐标与(x,y)相同的美丽点都不能同时作为答案。

其他的,也就是xy坐标均与(x,y)不相同的,设其坐标为(a,b),那么(a,b)(x,y)能够同时作为答案当且仅当(a,b)(x,y)的右下方。或者(x,y)(a,b)的右下方。注意是严格的右下方。

至此本题就基本做完了。代码实现也很简单。

T1
// 删掉了一些调试信息以免引起各位的极度不适
#include <iostream>
#define GMY (520&1314)
#define FBI_OPENTHEDOOR(x) freopen(#x ".in", "r", stdin), freopen(#x ".out", "w", stdout);
#define re register int
#define char_phi signed
#define MARK cout << "###"
#define MARKER "@@@"
#define LMARK "!!!~~~"
#define ZY " qwq "
#define _ " "
#define Endl cout << '\n'
#define MIN(x, y) (((x) < (y)) ? (x) : (y))
#define MAX(x, y) (((x) > (y)) ? (x) : (y))
#define N 1005
#define CASE 12
using namespace std;
inline void Fastio_setup(){ios::sync_with_stdio(false); cin.tie(NULL), cout.tie(NULL);}
/*
	好一个传纸条dp
	爆搜是吗
	我瞎搞直接输出草
	n = 2的数据好弄,那个小性质直接搞一下输出就行?
	其他的,我试试
	只能向下或者向右走
	好
	对于一个右-下点 (i, j),(i+2, j)、(i, j+2)都不能作为另一个【正确的】点
	其他的都可以
	那么对于右-下点们进行排序
	首先满足x升序
	再满足y升序
	然后直接大力分类讨论
	最坏情况下时间复杂度:O(n^4)
	草
	不对似乎并不是如此
	可以O(n^2)预处理分一下块
	直接开二维数组存不就行了
	特殊判断一下点(n, m)
	似乎涉及到
	二维线段树?
	我不会二维线段树
	所以我写个假的二维线段树
	浅算了一下完全能开的下
	好
	O(n^3 logn)大概
	超!
	然而并不知道这个理论是否正确
	所以大概率会寄掉
	我维护个粑粑的线段树
	我就n^4枚举咋地
	也不知道能不能行
	超!
*/
bool final_ans;
int T, n, m, cnt;
char s[N][N];
struct Down_Right{int x, y;}a[N*N];
inline void Clean(){
	final_ans = false; cnt = 0;
}
void work(){
	Clean();
	cin >> n >> m;
	for (re i = 1 ; i <= n ; ++ i)
		cin >> s[i]+1;
	for (re i = 1 ; i <= n ; ++ i)
		for (re j = 1 ; j <= m ; ++ j)
			if (s[i][j+1] == s[i+1][j] and (i != n and j != m))
				a[++ cnt].x=i, a[cnt].y=j;
	for (re i = 1 ; i <= cnt ; ++ i){
		for (re j = i+1 ; j <= cnt ; ++ j){
			// 在同一行
			if (a[i].x == a[j].x){
				if (a[j].y == a[i].y+1)
					{final_ans = true; goto Breaker;}
			}
			// 在同一列
			else if (a[i].y == a[j].y){
				if (a[j].x == a[i].x+1)
					{final_ans = true; goto Breaker;}
			}
			// x、y都不相同
			else 
				{final_ans = true; goto Breaker;}
		}
	}
	Breaker:{}
	cout << final_ans << '\n';
}
#define IXINGMY
char_phi main(){
	#ifdef IXINGMY
		FBI_OPENTHEDOOR(water);
	#endif
	Fastio_setup();
	cin >> T;
	while (T --)
		work();
	return GMY;
}

T2 AVL

我超!平衡树!跳跳跳...

这个题不会。。我连splay都没学。。

虽然考的并不是平衡树但是

并不妨碍我骗分。

除了根节点输出1之外,别的都输出0,可以获得9pts的好成绩。

代码不挂了,丢人。。。

T3 

我想喷一下出题人的语文水平。。。

浅问了一下,赛时大家基本都没读懂题。。

这题目描述就是个barbar ———CDsidi

这第二段就是个barbar ———CDsidi

第二段确实描述的令人难以理解,这让我想起了《生活在树上

他其实叨叨了半天就是正常的积水,只不过两边(边界)没有积水而已(可以认为是边界再往外是平地)。

其实是个神仙题,我不会,我贺题解

T3
#include <iostream>
#include <set>
#include <map>
#include <algorithm>
#define GMY (520&1314)
#define FBI_OPENTHEDOOR(x) freopen(#x ".in", "r", stdin), freopen(#x ".out", "w", stdout);
#define re register int
#define char_phi signed
#define MARK cout << "###"
#define MARKER "@@@"
#define LMARK "!!!~~~"
#define ZY " qwq "
#define _ " "
#define Endl cout << '\n'
#define MIN(x, y) (((x) < (y)) ? (x) : (y))
#define MAX(x, y) (((x) > (y)) ? (x) : (y))
#define N 25002
#define P 1000000007
#define KKK 26
#define mod %
using namespace std;
inline void Fastio_setup(){ios::sync_with_stdio(false); cin.tie(NULL), cout.tie(NULL);}
/*
	神仙题
	思考无果
	贺题解
*/
/*
7 1
2 5 2 4 1 6 2
*/
int n, K, final_ans;
int h[N], id[N];
struct Dynamic_Programming{
	int a[N], cnt[N]; int val[N][KKK]; int dp[N][KKK][KKK][3];
	multiset<int> s; map<int, int> mp[N];
	multiset<int>::iterator it;
	void prew(){
		s.insert(0);
		for (re i = 1 ; i <= n ; ++ i){
			s.insert(a[i]), it = s.end();
			for (re j = 1 ; j <= K+1 ; ++ j){
				if (it == s.begin())
					break;
				it = prev(it), mp[i][*it] = ++ cnt[i], val[i][cnt[i]] = *it;
			}
		}
		dp[0][1][0][0] = 1; cnt[0] = 1; val[0][1] = 0;
		for (re i = 0 ; i <= n-1 ; ++ i){
			for (re j = 1 ; j <= cnt[i] ; ++ j){
				for (re k = 0 ; k <= K ; ++ k){
					for (re p = 0 ; p <= 1 ; ++ p){
						if (dp[i][j][k][p] == 0)
							continue;
						if (val[i][j] >= a[i+1]){
							int nxj = mp[i+1][val[i][j]], nxp = p ^ ((val[i][j]-a[i+1]) & 1);
							dp[i+1][nxj][k][nxp] = (dp[i+1][nxj][k][nxp] + dp[i][j][k][p]) mod P;
							nxp = p ^ (val[i][j] & 1);
							if (k+1 <= K)
								dp[i+1][nxj][k+1][nxp] = (dp[i+1][nxj][k+1][nxp] + dp[i][j][k][p]) mod P;
						}
						else {
							int nxj = mp[i+1][a[i+1]], nxp = p ^ (val[i][j] & 1);
							dp[i+1][nxj][k][p] = (dp[i+1][nxj][k][p] + dp[i][j][k][p]) mod P;
							nxj = mp[i+1][val[i][j]];
							if (k+1 <= K)
								dp[i+1][nxj][k+1][nxp] = (dp[i+1][nxj][k+1][nxp] + dp[i][j][k][p]) mod P;
						}
					}
				}
			}
		}
	}
}f, g;// 正 和 反
// Hikari and Taritsu (doge
inline bool comp(int i, int j){return h[i] > h[j];}
void work(){
	cin >> n >> K;
	for (re i = 1 ; i <= n ; ++ i)
		{cin >> h[i]; id[i] = i, f.a[i] = g.a[n-i+1] = h[i];}
	f.prew(), g.prew();
	sort(id+1, id+n+1, comp);
	for (re i = 1 ; i <= n ; ++ i){
		if (h[id[i]] < h[id[K+1]])
			break;
		int x = id[i], w = h[id[i]];
		for (re j = f.cnt[x-1] ; j >= 1 ; -- j){
			if (f.val[x-1][j] > w)
				break;
			for (re k = g.cnt[n-x] ; k >= 1 ; -- k){
				if (g.val[n-x][k] >= w)
					break;
				for (re d = 0 ; d <= K ; ++ d){
					final_ans = (final_ans + (long long)f.dp[x-1][j][d][0] * g.dp[n-x][k][K-d][0] mod P) mod P;
					final_ans = (final_ans + (long long)f.dp[x-1][j][d][1] * g.dp[n-x][k][K-d][1] mod P) mod P;
				}
				// cerr << final_ans << '\n';
			}
		}
	}
	/*for (re i = 1 ; i <= n ; ++ i)
		cout << id[i] << '\n';*/
	/*for (re i = 1 ; i <= n ; ++ i){
		for (re j = 1 ; j <= K ; ++ j){
			for (re k = 1 ; k <= K ; ++ k){
				for (re p = 0 ; p <= 1 ; ++ p){
					cout << g.dp[i][j][k][p] << _;
				}
				cout << '\n';
			}
		}
	}*/
	/*for (re i = 1 ; i <= n ; ++ i)
		for (re k = 1 ; k <= K ; ++ k)
			cout << f.val[i][k] << _ << g.val[i][k] << '\n';*/
	/*cerr << n << _ << K;
	for (re i = 1 ; i <= n ; ++ i)
		cerr << h[i] << _;
	cerr << '\n';*/
	cout << final_ans << '\n';
}
#define IXINGMY
char_phi main(){
	#ifdef IXINGMY
		FBI_OPENTHEDOOR(rain);
	#endif
	Fastio_setup();
	work();
	return GMY;
}

T4 

这题我也不会,连题解都没贺,但是难度比T3要小?

暴力是环长直接求个LCM,有10pts

T4·暴力10pts
#include <iostream>
#include <algorithm>
#include <cstring>
#define GMY (520&1314)
#define FBI_OPENTHEDOOR(x) freopen(#x ".in", "r", stdin), freopen(#x ".out", "w", stdout);
#define re register int
#define char_phi signed
#define MARK cout << "###"
#define MARKER "@@@"
#define LMARK "!!!~~~"
#define ZY " qwq "
#define _ " "
#define Endl cout << '\n'
#define MIN(x, y) (((x) < (y)) ? (x) : (y))
#define MAX(x, y) (((x) > (y)) ? (x) : (y))
#define N 205
#define mod %
using namespace std;
inline void Fastio_setup(){ios::sync_with_stdio(false); cin.tie(NULL), cout.tie(NULL);}
int n, P, fz, fm, tpz, tpm;
char vis[N];
int a[N];
inline long long ksm(long long A, long long B){
	long long res(1);
	while (B != 0){
		if ((B & 1) == 1) res = res * A mod P;
		A = A * A mod P;
		B >>= 1;
	}
	return res;
}
long long gcd(long long x, long long y){return ((y == 0) ? (x) : (gcd(y, x%y)));}
inline long long LCM(long long x, long long y){return (x * y / gcd(x, y));}
void work(){
	cin >> n >> P;
	for (re i = 1 ; i <= n ; ++ i)
		a[i] = i;
	fm = 1;
	for (long long i = n ; i >= 2 ; -- i)
		fm = fm * i mod P;
	do{
		tpz = 1; memset(vis, false, sizeof(vis));
		for (re i = 1 ; i <= n ; ++ i){
			if (vis[i] == true)
				continue;
			int x = i, num(0);
			while (vis[x] == false)
				vis[x] = true, x = a[x], num ++;
			tpz = LCM(tpz, num);
		}
		tpz = tpz * tpz mod P;
		fz = (fz + tpz) mod P;
	}while (next_permutation(a+1, a+n+1));
	// cerr << fz << _ << fm << '\n';
	cout << fz * ksm(fm, P-2) mod P << endl; 
}
#define IXINGMY
char_phi main(){
	#ifdef IXINGMY
		FBI_OPENTHEDOOR(perm);
	#endif
	Fastio_setup();
	work();
	return GMY;
}
posted @   char_phi  阅读(4)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示