1. 程式人生 > >AtCoder Regular Contest 099 題解

AtCoder Regular Contest 099 題解

題意:

給出一個操作序列包含<>+<>+-,分別是下標左移右移,當前位置加減。問有多少對(i,j)(i,j)滿足只做這裡面的操作,結果和做完所有操作一樣。

題解:

很神奇的一道題。 首先將操作後得到的序列看成一個多項式:T(S)=i=109109aixiT(S)=\sum_{i=-10^9}^{10^9}a_ix^i 考慮在操作序列前加操作,多項式會變成什麼 t(>S)=T(S)xt(>S)=T(S)x

t(<

S)=T(S)x1t(<S)=T(S)x^{-1}

t(+S)=T(S)+1t(+S)=T(S)+1

t(S)=T(S)1t(-S)=T(S)-1

給整個多項式一個hash值c,那麼就是問多少對(i,j)(i,j)滿足這樣得出來的序列的hash等於c。 這四個操作顯然是可逆的,設(i,j)(i,j)中的操作為tsitsi+1tsi+2tsjt_{s_i}t_{s_{i+1}}t_{s_{i+2}}…t_{s_{j}}逆操作為t

si1tsi+11tsi+21tsj1t_{s_i}^{-1}t_{s_{i+1}}^{-1}t_{s_{i+2}}^{-1}…t_{s_{j}}^{-1} tsitsi+1tsi+2tsj(0)=ct_{s_i}t_{s_{i+1}}t_{s_{i+2}}…t_{s_{j}}(0)=c

tsn1tsn11tsn21tsi1tsitsi+1tsi+2tsj(0)=tsn1tsn11tsn21tsi1(c)t_{s_n}^{-1}t_{s_{n-1}}^{-1}t_{s_{n-2}}^{-1}…t_{s_{i}}^{-1}t_{s_i}t_{s_{i+1}}t_{s_{i+2}}…t_{s_{j}}(0)=t_{s_n}^{-1}t_{s_{n-1}}^{-1}t_{s_{n-2}}^{-1}…t_{s_{i}}^{-1}(c)

tsn1tsn11tsn21tsj+11(0)=tsn1tsn11tsn21tsi1(c)t_{s_n}^{-1}t_{s_{n-1}}^{-1}t_{s_{n-2}}^{-1}…t_{s_{j+1}}^{-1}(0)=t_{s_n}^{-1}t_{s_{n-1}}^{-1}t_{s_{n-2}}^{-1}…t_{s_{i}}^{-1}(c) 變成兩個字尾形式,可以線性求出hash值,map統計即可。 自己寫的怎麼都過不了,各種hash被卡,抄了別人寫法 WA:

#include<map>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#define LL long long
#define MP make_pair
using namespace std;
const LL mod=1e9+7;
LL base[4],pre[4][500010],inv[4];
struct node{LL a,b;}op[4][250010];
map<pair<pair<LL,LL>,pair<LL,LL> >,LL> mp;
LL pow(LL a,LL b)
{
	LL ans=1;
	while(b)
	{
		if(b&1) ans=ans*a%mod;
		a=a*a%mod;b>>=1;
	}
	return ans;
}
LL n,p=0,t[500010],c[4],a[4][250010],b[4][250010];
char s[250010];
void Pre()
{
	for(int k=0;k<4;k++)
	{
		LL cnt=1;op[k][n+1].a=1;
		for(LL i=n;i>=1;i--)
		{
			op[k][i]=op[k][i+1];
			if(s[i]=='<') cnt=cnt*base[k]%mod,(op[k][i].a*=base[k])%=mod;
			if(s[i]=='>') cnt=cnt*inv[k]%mod,(op[k][i].a*=inv[k])%=mod;
			if(s[i]=='-') (op[k][i].b+=cnt*pre[k][n]%mod)%=mod;
			if(s[i]=='+') op[k][i].b=((op[k][i].b-cnt*pre[k][n]%mod)%mod+mod)%mod;
		}
	}
}
void solve(LL *a,LL c,LL k) {for(LL i=1;i<=n;i++) a[i]=(c*op[k][i].a%mod+op[k][i].b)%mod;}
int main()
{
	base[0]=2333;base[1]=10037;base[2]=19260817;base[3]