CSP-S模拟40/炼石计划NOIP模拟赛第五套

歇宰迁main:

大大大大大家好我我我是肝· \(HZOI\) 爆零大玉·硬化,今今今今今天我又双叒叕爆零啦【大悲】。我的 \(S\) 组怎么办啊么办啊么办啊么办啊么办啊么办啊么办啊么办啊么办啊!!!

image
image
image

《医学》

ドクター・キドリです
愛・爆破ッテロ
簡単になれば
埋まった マター マター
ドクター・キドリです
愛想良いかも
朦朧オオトも 埋めた メタ メタ
何処にも無いから寝ていたら
壊れて泣いてるユメを診たんだよ
次期には嘘に診えてクルゥ
カオが→鈍器になっちゃうヨ
偽が→権利を取ったんだ
無くなってほしい煩悩が
ドウヤラ生き延びてしまった
生き延びてしまったんだ
足が→タガメになっちゃうヨ
嘘が→動機になったんだ
疑ってほしい本能を
ドウヤラ本心だと思った
本心だと思ったんだ
クチョォ
ドクター・キドリです
全部辞めろよ
アティチュードが
感動物に届く猛毒
損得の得の方ダケ
回った 割った 割った
カオが→鈍器になっちゃうヨ
偽が→権利を取ったんだ
無くなってほしい煩悩が
ドウヤラ生き延びてしまった
生き延びてしまったんだ
音が→機能になってしまう
人が→偽りに集まる
塞がってしまえよ耳
ドウヤラ届いて居ない診たい
届いて居ない診たいネ゛
クチョォ


T1 公约数神庙

喵。

题目描述:

自己发明。

土地私有制使得贤者成为谜语人,全职神喵不是群居动物,若 \(i\leq j\) 且 两者的 \(_{Gong^{产_{党}}}\) 大于一,那么你可以从神喵 \(i\) 走到神喵 \(j\) ,不管世界上有多少 \(_{共_{Chan_党}}\),神喵自己都能走到自己, \(0\) 没有\(共_{产^{Dang}}\)


Solve:

先说赛时罢:

首先我们可以发现我们不会。于是我们先观察数据范围发现 \(a_i\) 只有 \(1000\) 这启发我们先筛个质数
const int cnt = 168, pr[] = {0, 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631, 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 743, 751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829, 839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997};

对不起!

然后暴力地分解质因数:

for(register int i = 1; i <= n; i ++){
		a[i] = r();
		int hh = a[i];
		for(register int j = 1; hh > 1; j ++){
			if(hh % pr[j] == 0){
				while(hh % pr[j] == 0){
					hh /= pr[j];
				}
			}
		}
	}

太劣了!

之后我们发现如果左右端点两个数的 \(gcd\) 大于一就一定可行,于是特判输出 \(Shi\)

真没治!

但是还有一种情况就是这样的:
image
二通过六和二十一可以到与它没有共同质因数的七。
于是我们发现可以把所有有共同质因数的点都连上边。
image

炸炸炸炸炸炸炸!

于是我们每次拆到一个质因数都只和上一次刚刚出现那个质因数的位置连有向边。
image

会不会炸!

不知道,让我们拿出智慧的计算器,摁一下,发现一千以内的数最多有四个不相同的质因数,于是最多建出 \(4×(n-1)\) 条边,炸不了。

这么好!

但是每次询问跑一遍电风扇 \(DFS\)\(O(n)\) 的,不过可以得到前 \(80pts\) 了。

你要不看看样例过了吗!

没有。
我们惊奇地发现:我们刚刚的操作建了整整零条边!按理来说应该只有自己到自己的地方是 \(Shi\) 口牙,为什么还有一个呢?
零与其它不为零的数的最大公约数在本题竟然等于那个数!!!
那我难道要让零跟每个点都连条边吗?

炸炸炸炸炸炸炸!

这是赛时,我想不到正解的前缀和,但是直接跑太劣了,加边太爆炸了,于是为了维护 \([x,y]\) 区间是否存在 \(0\) ,我自以为是地写了一棵线段树

人傻常数大,全部都爆炸!

于是我用的其实是 \(bool\) ,然后就是很高兴,没写假。

然后每次暴力 \(DFS\) 时清空 \(v\) 数组太唐了于是改成了记时间戳。

然后呢?

然后自己发明了两个小样例给自己 \(Hack\) 了。

1:

5 2
1 0 1 0 1
1 5
2 4

Expect:

Fou
Fou

2:

5 1
1 0 3 0 1
2 4

Expect:

Shi

坏了少特判!

于是我就特判了两头是一的/两头是零且中间没比一大的是 \(Fou\) ,两头是零且中间有比一大的是 \(Shi\)

对不起注意力太差了没发现只有一头是一也是 \(Fou\)

之后其实如果加上没发现的特判就能 \(AC\) 了,时间复杂度其实不会算,但是应该最坏最坏能到 \(O(n~q~logn)\) ,自带多少常数不会算,肯定跑不满,大抵是数据水可过罢。

《不使用快读快写/关闭流同步,仅使用 \(scanf\) 跑得严格快于 \(admin\) 的码》

啊啊啊我为什么少个特判啊啊啊啊啊啊啊啊!!!


Code:

想看卡常点这里
#include <bits/stdc++.h>
using namespace std;
#define lson (root << 1)
#define rson (root << 1 | 1)
#define mid ((l + r) >> 1)
const short cnt = 168, pr[] = {0, 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631, 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 743, 751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829, 839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997};
const int _ = 100010;
short a[_];
int x, y, nw, n, q, bfr[1001], to[_ << 2], nxt[_ << 2], h[_], tot, v[_];
bool t[_ << 2];
struct hhh{
	int x, y;
};
inline short gcd(short x, short y){
	return y ? gcd(y, x % y) : x;
}
inline int r(){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-'0');ch=getchar();}return x*f;}
inline void add(int x, int y){
	to[++ tot] = y;
	nxt[tot] = h[x];
	h[x] = tot;
	return ;
}
inline bool zhao(int s, int t){
	if(s == t){
		return 1;
	}
	if(s > t || v[s] == nw){
		return 0;
	}
	v[s] = nw;
	for(int i = h[s]; i; i = nxt[i]){
		int hhh = to[i];
		if(zhao(hhh, t)){
			return 1;
		}
	}
	return 0;
}
inline void update(int root, int l, int r, int p, int v){
	if(l == r){
		t[root] = v;
		return ;
	}
	if(p <= mid){
		update(lson, l, mid, p, v);
	}
	else{
		update(rson, mid + 1, r, p, v);
	}
	t[root] |= t[lson] | t[rson];
	return ;
}
inline bool query(int root, int l, int r, int x, int y){
	if(l >= x && r <= y){
		return t[root];
	}
	bool as = 0;
	if(x <= mid){
		as |= query(lson, l, mid, x, y);
	}
	if(y > mid){
		as |= query(rson, mid + 1, r, x, y);
	}
	return as;
}
int main(){
	freopen("gcd.in", "r", stdin);
	freopen("gcd.out", "w", stdout);
	n = r(), q = r();
	for(register int i = 1; i <= n; i ++){
		a[i] = r();
		short hh = a[i];
		if(! hh){
			update(1, 1, n, i, 1);
			continue;
		}
		for(register int j = 1; hh > 1; j ++){
			if(hh % pr[j] == 0){
				while(hh % pr[j] == 0){
					hh /= pr[j];
				}
				if(bfr[pr[j]]){
					add(bfr[pr[j]], i);
				}
				bfr[pr[j]] = i;
			}
		}
	}
	for(register int i = 1; i <= q; i ++){
		nw ++;
		x = r(), y = r();
		register short miao = gcd(a[x], a[y]);
		if(x == y){
			putchar('S'), putchar('h'), putchar('i'), putchar('\n');
			continue;
		}
		else if(miao > 1){
			putchar('S'), putchar('h'), putchar('i'), putchar('\n');
			continue;
		}
		else if(a[x] == 1 || a[y] == 1){
			putchar('F'), putchar('o'), putchar('u'), putchar('\n');
			continue;
		}
		else if(! a[x] && ! a[y]){
			bool f = 0;
			for(int j = x; j < y; j ++){
				if(a[j] > 1){
					f = 1;
					break;
				}
			}
			f ? (putchar('S'), putchar('h'), putchar('i'), putchar('\n')) : (putchar('F'), putchar('o'), putchar('u'), putchar('\n'));
			continue;
		}
		else if(query(1, 1, n, x, y)){
			putchar('S'), putchar('h'), putchar('i'), putchar('\n');
			continue;
		}
		else{
			zhao(x, y) ? (putchar('S'), putchar('h'), putchar('i'), putchar('\n')) : (putchar('F'), putchar('o'), putchar('u'), putchar('\n'));
		}
	}
	return 0;
}
#include <bits/stdc++.h>
using namespace std;
#define lson (root << 1)
#define rson (root << 1 | 1)
#define mid ((l + r) >> 1)
const short cnt = 168, pr[] = {0, 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631, 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 743, 751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829, 839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997};
const int _ = 100010;
short a[_];
int x, y, nw, n, q, bfr[1001], to[_ << 2], nxt[_ << 2], h[_], tot, v[_];
bool t[_ << 2];
struct hhh{
	int x, y;
};
inline short gcd(short x, short y){
	return y ? gcd(y, x % y) : x;
}
inline int r(){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-'0');ch=getchar();}return x*f;}
inline void add(int x, int y){
	to[++ tot] = y;
	nxt[tot] = h[x];
	h[x] = tot;
	return ;
}
inline bool zhao(int s, int t){
	if(s == t){
		return 1;
	}
	if(s > t || v[s] == nw){
		return 0;
	}
	v[s] = nw;
	for(int i = h[s]; i; i = nxt[i]){
		int hhh = to[i];
		if(zhao(hhh, t)){
			return 1;
		}
	}
	return 0;
}
inline void update(int root, int l, int r, int p, int v){
	if(l == r){
		t[root] = v;
		return ;
	}
	if(p <= mid){
		update(lson, l, mid, p, v);
	}
	else{
		update(rson, mid + 1, r, p, v);
	}
	t[root] |= t[lson] | t[rson];
	return ;
}
inline bool query(int root, int l, int r, int x, int y){
	if(l >= x && r <= y){
		return t[root];
	}
	bool as = 0;
	if(x <= mid){
		as |= query(lson, l, mid, x, y);
	}
	if(y > mid){
		as |= query(rson, mid + 1, r, x, y);
	}
	return as;
}
int main(){
	freopen("gcd.in", "r", stdin);
	freopen("gcd.out", "w", stdout);
	scanf("%d%d", & n, & q);
	for(register int i = 1; i <= n; i ++){
		scanf("%d", & a[i]);
		short hh = a[i];
		if(! hh){
			update(1, 1, n, i, 1);
			continue;
		}
		for(register int j = 1; hh > 1; j ++){
			if(hh % pr[j] == 0){
				while(hh % pr[j] == 0){
					hh /= pr[j];
				}
				if(bfr[pr[j]]){
					add(bfr[pr[j]], i);
				}
				bfr[pr[j]] = i;
			}
		}
	}
	for(register int i = 1; i <= q; i ++){
		nw ++;
		scanf("%d%d", & x, & y);
		register short miao = gcd(a[x], a[y]);
		if(x == y){
			printf("Shi\n");
			continue;
		}
		else if(miao > 1){
			printf("Shi\n");
			continue;
		}
		else if(a[x] == 1 || a[y] == 1){
			printf("Fou\n");
			continue;
		}
		else if(! a[x] && ! a[y]){
			bool f = 0;
			for(int j = x; j < y; j ++){
				if(a[j] > 1){
					f = 1;
					break;
				}
			}
			f ? (printf("Shi\n")) : (printf("Fou\n"));
			continue;
		}
		else if(query(1, 1, n, x, y)){
			printf("Shi\n");
			continue;
		}
		else{
			zhao(x, y) ? (printf("Shi\n")) : (printf("Fou\n"));
		}
	}
	return 0;
}

T2 栈法师

我讨厌模拟,我看着就觉得恶心。

Solve:

一些人:
image

根据题意,我们需要按不降序砍死他们,但是我们必须把他们转移到一个栈里才能用弹栈的方式砍死。

我们可以这样搞:
image
image
image
image
image
image

\(C_{a}o\) 了粘完才发现是个藏头的东西(啊啊啊啊啊啊大大大大大大大大大哥别杀我!!!)

这样的东西是平凡的,直接模拟一下就可以了。

再看这群人:
image

我们还是这样杀:
image
image
image
image

我们发现了一个可怕的事情——
我们杀不了他了:
image

于是只能新开一个栈来中转:
image
image
image

终于杀完啦!

于是我们直接模拟 \(k=1\) 的情况,如果不行那么 \(k\) 就等于二。(这不废话)
把弹出的数都放入栈法杖 A 中,栈法杖 B 仅作为中转,设下一个要输出的数为 \(x\)
\(x\) 还在序列 \(a\) 中,则一直进行 \((1, 1)\) 操作直到 \(x\) 进入栈法杖 A,然后进行一次 \((2, 1)\) 操作将其输出;操作次数 = 当前序列 \(a\) 长度 - \(x\) 初始位置 + 1。

否则 \(x\) 在栈法杖 A 中,进行 \((3, 1, 2)\) 操作直到 \(x\) 是栈顶,进行一次 \((2, 1)\) 操作将其输出,然后进行 \((3, 2, 1)\) 操作清空栈法杖 B;操作次数 = 当前 \(A\) 栈 size - \(x\) 初始位置之后 \(<x\) 元素数量 - 1。

\(x\) 初始位置之后 \(<x\) 元素数量" 可以使用树状数组预处理。

总复杂度 \(O(n\log n)\)


Code:

#include <bits/stdc++.h>
#define lowbit(x) (x & (- x))
const int _ = 100005;
int t, b[_], tree[_], p[_], n, s[_], top;
std::vector<int> v;
struct hhh{
	int n, v;
}a[_];
inline bool bbb(hhh x, hhh y){
	if(x. v != y. v){
		return x. v < y. v;
	}
	return x. n < y. n;
}
inline void add(int x, int y){
	for(; x <= n; x += lowbit(x)){
		tree[x] += y;
	}
	return ;
}
inline int query(int x){
	int as = 0;
	for(; x; x -= lowbit(x)){
		as += tree[x];
	}
	return as;
}
inline bool kdyi(){//k==1。
	v. clear();
	top = 0;
	for(int i = 1, nw = n; i <= n; i ++){
		while((! top || s[top] != a[i]. v) && nw){
			s[++ top] = b[nw --];
			v. emplace_back(1);
		}
		if(s[top] == a[i]. v){
			v. emplace_back(0);
			top --;
		}
		else{
			return 0;
		}
	}
	return 1;
}
inline void kder(){
	v. clear();
	for(int i = 1; i <= n; i ++){
		p[i] = n - a[i]. n + 1;
	}
	for(int i = 1; i <= n; i ++){
		add(i, 1);
	}
	for(int i = 1, c = n; i <= n; i ++){
		int d = query(p[i]) - query(c);
		if(d){
			v. emplace_back(d);
		}
		v. emplace_back(0);
		add(c = p[i], - 1);
	}
	printf("2\n%d\n1 1 %d\n", v. size() + 1, n);
	for(auto h : v){
		if(h > 0){
			printf("3 2 1 %d\n", h);
		}
		if(h < 0){
			printf("3 1 2 %d\n", - h);
		}
		if(! h){
			printf("2 1\n");
		}
	}
	return ;
}
int main(){
	freopen("sort.in", "r", stdin);
	freopen("sort.out", "w", stdout);
scanf("%d", & t);
while(t --){
	scanf("%d", & n);
	for(int i = 1; i <= n; i ++){
		scanf("%d", & b[i]);
		a[i]. v = b[i], a[i]. n = i;
	}
	std::sort(a + 1 , a + n + 1, bbb);
	if(kdyi()){
		printf("1\n%d\n", v. size());
		for(auto h : v){
			h ? printf("1 1 1\n") : printf("2 1\n");
		}
	}
	else{
		kder();
	}
}
	return 0;
}

T3 城堡考古

城城堡(\(ccb\))。

不知道我不会我赛时就看出来 \(m=2\) 是斐波那契数列然后矩阵快速幂也不知道写没写真然后不会高级的数学也来不及而且不会神秘的高精度于是遗憾离场咕咕咕。

T4 生命之树

生命女神!

image
image
image

依旧不会。

END.

posted @ 2025-10-27 21:03  养鸡大户肝硬化  阅读(39)  评论(4)    收藏  举报