• arc099_f Eating Symbols Hard


    arc099_f Eating Symbols Hard

    https://atcoder.jp/contests/arc099/tasks/arc099_d

    Snipaste_2020-06-30_15-33-19.png

    Tutorial

    https://img.atcoder.jp/arc099/editorial.pdf

    考虑用哈希来判断序列的相等.设(A)的哈希值为(f(A)=sum A_ibase^i),设(g(S))表示(S)生成的序列(A)(f(A))

    那么+-<>对哈希值的影响为

    • (g(+S)=g(S)+1)
    • (g(-S)=g(S)-1)
    • (g(>S)=g(S)base)
    • (g(<S)=g(S)base^{-1})

    发现第(i)个字符可以表示为一次函数 (h_i) 的形式.

    (c=g(S)),我们要求的就是((i,j))满足

    [h_i circ h_{i+1} cdots circ h_j(0) = c \ h_n^{-1} circ h_{n-1}^{-1} cdots circ h_i^{-1} circ h_{i+1} cdots circ h_j(0) = h_n^{-1} circ h_{n-1}^{-1} cdots circ h_i^{-1}(c) \ h_n^{-1} circ h_{n-1}^{-1} cdots circ h_{j+1}^{-1}(0) = h_n^{-1} circ h_{n-1}^{-1} cdots circ h_i^{-1}(c) ]

    那么用map即可求解.

    Code

    #include <cstdio>
    #include <cstdlib>
    #include <iostream>
    #include <map>
    #define debug(...) fprintf(stderr,__VA_ARGS__)
    #define inver(a,mod) power(a,mod-2,mod)
    #define idx(a,b) ((ll)(a)*mod[1]+(b))
    using namespace std;
    template<class T> void rd(T &x) {
    	x=0; int f=1,ch=getchar();
    	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    	while(ch>='0'&&ch<='9'){x=x*10-'0'+ch;ch=getchar();}
    	x*=f;
    }
    typedef long long ll;
    const int mod[2]={998244353,1004535809};
    const int maxn=250000+50;
    int bs[2],rb[2];
    int n; char s[maxn];
    int c[2];
    map<ll,int> cnt;
    struct func {
    	int k,b;
    	func(int k=1,int b=0):k(k),b(b){}
    	inline int f(int x,int mod) {
    		return ((ll)k*x+b)%mod;
    	}
    } a[maxn][2];
    inline func mer(func a,func b,int mod) {
    	return func((ll)a.k*b.k%mod,((ll)a.b*b.k+b.b)%mod);
    }
    inline int add(int x,int mod) {return x>=mod?x-mod:x;}
    inline int sub(int x,int mod) {return x<0?x+mod:x;}
    ll power(ll x,ll y,int mod) {
    	ll re=1;
    	while(y) {
    		if(y&1) re=re*x%mod;
    		x=x*x%mod;
    		y>>=1;
    	}
    	return re;
    }
    void init() {
    	srand((unsigned long long)(new char));
    	bs[0]=rand(),rb[0]=inver(bs[0],mod[0]);
    	bs[1]=rand(),rb[1]=inver(bs[1],mod[1]);
    }
    int main() {
    	init();
    	rd(n);
    	scanf("%s",s+1);
    	for(int i=n;i>=1;--i) for(int k=0;k<2;++k) {
    		func f; switch(s[i]) {
    			case '+': f=func(1,mod[k]-1),c[k]=add(c[k]+1,mod[k]); break;
    			case '-': f=func(1,1),c[k]=sub(c[k]-1,mod[k]); break;
    			case '>': f=func(rb[k],0),c[k]=(ll)c[k]*bs[k]%mod[k]; break;
    			case '<': f=func(bs[k],0),c[k]=(ll)c[k]*rb[k]%mod[k]; break;
    		}
    		a[i][k]=mer(f,a[i+1][k],mod[k]);
    	}
    	ll an=0;
    	++cnt[0];
    	for(int i=n;i>=1;--i) {
    		an+=cnt[idx(a[i][0].f(c[0],mod[0]),a[i][1].f(c[1],mod[1]))];
    		++cnt[idx(a[i][0].f(0,mod[0]),a[i][1].f(0,mod[1]))];
    	}
    	printf("%lld
    ",an);
    	return 0;
    }
    
  • 相关阅读:
    03-es6语法 Promise 和 es8语法 async await 的了解和基本使用
    02-遍历数组的方法
    01-操作数组的方法
    position 几个属性的作用
    javascript---split 和 join 的区别
    微信sdk (1)
    php获取post参数的几种方式
    linux循环递归设置权限
    php汉字截取
    php汉字生成首字母
  • 原文地址:https://www.cnblogs.com/ljzalc1022/p/13214169.html
Copyright © 2020-2023  润新知