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;
}