AtCoderARC099 F - Eating Symbols Hard
Posted ivorysi
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了AtCoderARC099 F - Eating Symbols Hard相关的知识,希望对你有一定的参考价值。
题解
一道神奇的题
我们把操作S构成的A数组用一个多项式表示出来
(t(S) = sum_{i = -10^9}^{10^9} A_{i}X^{i})
如果往S前面添加一个字符的话
(t<(S) = t(S)X^{-1})
(t>(S) = t(S)X)
(t+(S) = t(S) + 1)
(t-(S) = t(S) - 1)
那么我们对于最终的序列求一个哈希值c,如果一段区间操作后的结果和c一样的话就有
(t_{S_i}t_{S_{i + 1}}...t_{S_j}(0) = c)
由于这些操作可逆,可以一层一层拆开
可以得到
(t_{S_N}^{-1}...t_{S_i}^{-1}t_{S_i}t_{S_{i + 1}}...t_{S_j}(0) = t_{S_N}^{-1}...t_{S_i}^{-1}(c))
那么我们可以得到
(t_{S_N}^{-1}...t_{S_{j + 1}}^{-1} (0) = t_{S_N}^{-1}...t_{S_{i}}^{-1}(c))
这个后缀积可以线性处理出来,维护未知数前的系数即可
然后就是愉快的用map查询了
那么,冲突怎么考虑?题解说是冲突的概率在2N/模数大小,让用6个,然而我写的不优美,T掉了,改成5个卡着时限A了,感觉用不上太多也是对的啊
代码
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <queue>
#include <cmath>
#include <map>
#define enter putchar(‘n‘)
#define space putchar(‘ ‘)
#define mp make_pair
#define pb push_back
#define fi first
#define se second
#define pii pair<int,int>
#define eps 1e-7
#define MAXN 250005
#define MOD 999999137
//#define ivorysi
using namespace std;
typedef long long int64;
typedef double db;
typedef vector<int> poly;
template<class T>
void read(T &res) {
res = 0;char c = getchar();T f = 1;
while(c < ‘0‘ || c > ‘9‘) {
if(c == ‘-‘) f = -1;
c = getchar();
}
while(c >= ‘0‘ && c <= ‘9‘) {
res = res * 10 + c - ‘0‘;
c = getchar();
}
res *= f;
}
template<class T>
void out(T x) {
if(x < 0) {putchar(‘-‘);x = -x;}
if(x >= 10) {
out(x / 10);
}
putchar(‘0‘ + x % 10);
}
int B[] = {0,823,727,401,271,571};
int InvB[10];
int f[8][MAXN],g[8][MAXN],N,h[8][MAXN];
char s[MAXN];
map<int,int> MK[8];
int mul(int a,int b) {
return 1LL * a * b % MOD;
}
int inc(int a,int b) {
return a + b >= MOD ? a + b - MOD : a + b;
}
void update(int &x,char c,int id) {
if(c == ‘<‘) x = mul(x,InvB[id]);
else if(c == ‘>‘) x = mul(x,B[id]);
else if(c == ‘+‘) x = inc(x,1);
else x = inc(x,MOD - 1);
}
int fpow(int x,int c) {
int res = 1,t = x;
while(c) {
if(c & 1) res = mul(res,t);
t = mul(t,t);
c >>= 1;
}
return res;
}
void Solve() {
for(int i = 1 ; i <= 5 ; ++i) InvB[i] = fpow(B[i],MOD - 2);
read(N);
scanf("%s",s + 1);
int c[10] = {0};
for(int k = 1 ; k <= 5 ; ++k) {
for(int i = N ; i >= 1 ; --i) {
update(c[k],s[i],k);
}
}
for(int k = 1 ; k <= 5 ; ++k) h[k][N + 1] = 1,g[k][N + 1] = c[k],MK[k][0] += 1;
int64 ans = 0;
for(int i = N ; i >= 1 ; --i) {
int add = N - i + 1;
for(int k = 1 ; k <= 5 ; ++k) {
if(s[i] == ‘<‘) {
g[k][i] = inc(g[k][i + 1],MOD - mul(h[k][i + 1],c[k]));
h[k][i] = mul(h[k][i + 1],B[k]);
g[k][i] = inc(g[k][i],mul(h[k][i],c[k]));
f[k][i] = f[k][i + 1];
}
else if(s[i] == ‘>‘) {
g[k][i] = inc(g[k][i + 1],MOD - mul(h[k][i + 1],c[k]));
h[k][i] = mul(h[k][i + 1],InvB[k]);
g[k][i] = inc(g[k][i],mul(h[k][i],c[k]));
f[k][i] = f[k][i + 1];
}
else if(s[i] == ‘+‘) {
h[k][i] = h[k][i + 1];
g[k][i] = inc(g[k][i + 1],MOD - h[k][i]);
f[k][i] = inc(f[k][i + 1],MOD - h[k][i]);
}
else {
h[k][i] = h[k][i + 1];
g[k][i] = inc(g[k][i + 1],h[k][i]);
f[k][i] = inc(f[k][i + 1],h[k][i]);
}
add = min(add,MK[k][g[k][i]]);
MK[k][f[k][i]] += 1;
}
ans += add;
}
out(ans);enter;
}
int main() {
#ifdef ivorysi
freopen("f1.in","r",stdin);
#endif
Solve();
return 0;
}
以上是关于AtCoderARC099 F - Eating Symbols Hard的主要内容,如果未能解决你的问题,请参考以下文章
AtCoderARC067 F - Yakiniku Restaurants 单调栈+矩阵差分
1609[Usaco2008 Feb]Eating Together麻烦的聚餐