總結——關於2017 10 16測試的分析總結

本文解析了NOIP2017模拟赛三道题目的解题思路及代码实现,包括匹配问题的绝对值符号确定法、块移动问题的双端BFS搜索策略以及字符串匹配问题的AC自动机构建方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

NOIP 2017 模拟


2017 10 16



T1 : match




题目 :






——正解思路 :

可以证明, 求最小值时打开绝对值之后符号是确定的。



——我的乱搞 :

**没有乱搞!!同正解。



tips : 

一般noip第一题都不会太难, tm去年day2t1炸得一逼,数学题什么的好好找规律吧。








稳得一逼。。



#pragma GCC optimize("O3")

#include <cstdio>
#include <cctype>

inline long long Read () {
	long long i = 0;
	char c = getchar();
	while (!isdigit(c)) c = getchar();
	while (isdigit(c)) i = (i << 3) + (i << 1) + c - 48, c = getchar();
	return i;
}

int main (int argc, char* argv[], char* env[]) {
	long long N, X = 0, Y = 0;
	N = Read();
	for (int i = 1; i <= N; i++) {
		X -= Read();
		Y += Read();
	}
	for (int i = 1; i <= N; i++) {
		X += Read();
		Y -= Read();
	}
	printf("%I64d\n", X + Y);
	return 0;
}






T2 : blocks


题目:




——正解思路 :

双端BFS搜索。

A*说不定也可以搜过去。


——我的乱搞 :

绝对乱搞,暴搜+伪剪枝,光荣gg。


tips : 

像搜索这类的题,如果憋不出正解那么只能靠我们优秀的暴搜技巧了。好好学习,天天暴搜。没事USACO上多训练暴搜吧,反正那儿数据水得一逼。





来来来, 附正解:


#pragma GCC optimize("O3")

#include <cstdio>
#include <cctype>
#include <queue>
#include <map>
#include <algorithm>

using namespace std;

typedef long long LL;

struct node{
	int x, y, step;
	bool tp;
	int mp[6][6];
};

map <LL, int> book[2];
queue <node> q;

const int dx[4] = {-1, -1, 1, 1};
const int dy[4] = {-1, 0, 0, 1};

inline int Read () {
	int i = 0;
	char c = getchar();
	while (!isdigit(c)) c = getchar();
	while (isdigit(c)) i = (i << 3) + (i << 1) + c - 48, c = getchar();
	return i;
}

inline LL hash(node &t) {
	long long tmp = 0;
	for (int i = 0; i <= 5; i++)
		for (int j = 0; j <= i; j++)
			tmp = tmp * 6 + t.mp[i][j];
	return tmp;
}

inline int bfs (node &s, node &t) {
	while (!q.empty()) q.pop();
	book[0].clear();
	book[1].clear();
	s.step = t.step = 0;
	s.tp = 0;
	t.tp = 1;
	book[0][hash(s)] = book[1][hash(t)] = 0;
	q.push (s);
	q.push (t);
	while (!q.empty()) {
		node x, a = q.front();
		q.pop();
		LL tmp = hash(a);
		if (book[!a.tp].count(tmp))
			if (book[!a.tp][tmp] + a.step <= 20)
				return book[!a.tp][tmp] + a.step;
			else
				continue;
		if (a.step >= 10) continue;
		for (int i = 0; i <= 3; i++) {
			x = a;
			x.x += dx[i];
			x.y += dy[i];
			if (x.x >= 6 || x.y > x.x || x.x < 0 || x.y < 0) continue;
			swap (x.mp[x.x][x.y], x.mp[a.x][a.y]);
			tmp = hash(x);
			if (book[x.tp].count(tmp)) continue;
			book[x.tp][tmp] = ++x.step;
			q.push(x);
		}
	}
	return -1;
}

int main (int argc, char* argv[], char* env[]) {
	int T = Read ();
	node s, t;
	while (T--) {
		for (int i = 0; i <= 5; i++)
			for (int j = 0; j <= i; j++) {
				s.mp[i][j] = Read();
				if(s.mp[i][j] == 0) {
					s.x = i;
					s.y = j;
				}
				t.mp[i][j] = i;
			}
		t.x = t.y = 0;
		int Ans = bfs(s, t);
		printf (Ans == -1 ? "too difficult\n" : "%d\n", Ans);
	}
	return 0;
}




T3 : string



题目 :




——正解思路:

建立AC自动机

由于每个匹配串比较短,所以修改当前点只会导致起始和终点在[ pos - | T | ,  pos + | T | ]这个范围内的匹配改变。所以每次把这个子串放入AC自动机中求有多少个匹配,调整答案即可。

——我的乱搞:

暴力修改并匹配。


tips :

贴吧上看了看,貌似有点超纲??!


呃。。如果考场上脑袋秀逗想不起这些高深莫测的算法时,有条件要乱搞,没有条件创造条件也要乱搞。










正解如下 :


#pragma GCC optimize("O3")

#include <cstdio>
#include <cctype>
#include <cstring>
#include <queue>
#include <algorithm>

using namespace std;

int n, m, all, pos, now, len, tot, maxx, minn, temp;
int w[100001], a[100001];
char s[1001][102];
char d[100002];

struct node {
	int cnt, fail;
	int son[26];
}trie[100001];

inline int read () {
	int i = 0;
	char c = getchar();
	while (!isdigit(c)) c = getchar();
	while (isdigit(c)) i = (i << 3) + (i << 1) + c - 48, c = getchar();
	return i;
}

inline void write (int x) {
	short num = 0;
	char c[10];
	do c[++num] = x%10 + 48, x/=10; while(x);
	while(num) putchar(c[num--]);
	putchar('\n');
}

inline void build (char* s) {
	int len = strlen(s), now = 0, temp;
	for (int i = 0; i < len; i++) {
		temp = s[i] - 'a';
		if (!trie[now].son[temp]) trie[now].son[temp] = ++tot;
		now = trie[now].son[temp];
	}
	trie[now].cnt++;
}

inline void GetFail () {
	static queue <int> q;
	for (int i = 0; i <= 25; i++)
		if (trie[0].son[i]) q.push(trie[0].son[i]);
	while (!q.empty()) {
		int u = q.front();
		q.pop();
		for (int i = 0; i <= 25; i++) {
			int v = trie[u].fail;
			if (!trie[v].son[i] && v) v = trie[v].fail;
			if (trie[u].son[i]) {
				trie[trie[u].son[i]].fail = trie[v].son[i];
				trie[trie[u].son[i]].cnt += trie[trie[v].son[i]].cnt;
				q.push(trie[u].son[i]);
			} else
				trie[u].son[i] = trie[v].son[i];
		}
	}
}

int main () {
	scanf("%d%d\n", &n, &m);
	for (int i = 1; i <= n; i++) {
		scanf ("%s\n", s[i]);
		maxx = max (maxx, (int)strlen(s[i]));
		build (s[i]);
	}
	scanf ("%s\n", d);
	GetFail ();
	len = strlen(d);
	for (int j  =0; j < len; j++) {
		temp = d[j] - 'a';
		if (now && !trie[now].son[temp]) now = trie[now].fail;
		now = trie[now].son[temp];
		a[j] = trie[now].cnt;
		all += trie[now].cnt;
		w[j] = now;
	}
	write (all);
	char c;
	for (int i = 1; i <= m; i++) {
		pos = read();
		do c = getchar(); while(c < 'a' || c > 'z');
		d[pos - 1] = c;
		now = (pos >= 2) ? w[pos - 2] : 0;
		minn = min (len, pos - 1 + maxx);
		for (int j = pos - 1; j < minn; j++) {
			temp = d[j] - 'a';
			if (now && !trie[now].son[temp]) now = trie[now].fail;
			now = trie[now].son[temp];
			w[j] = now;
			all += trie[now].cnt - a[j];
			a[j] = trie[now].cnt;
		}
		write (all);
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值