zoukankan      html  css  js  c++  java
  • CCPC2020长春 G题 Monkey's Keyboard

    链接:
    https://codeforces.com/gym/102832/problem/G

    Pro:
    给定一个

    Sol:
    很容易想到另一个题,叫歌唱王国。

    然后按照那道题的套路推一发式子

    发现对于任意一个字符串的

    [egin{align*} ans_S&=sum_{i,i is a border of S} prod_{j=1}^i frac{1}{p_i} \ &=sum_{i,i is a border of S} w_i (写成一个前缀积的形式) end{align*} ]

    发现这个式子的贡献
    只和border有关
    然后总答案的话可以考虑枚举border是谁
    然后算这个border的贡献是多少
    具体地说
    首先,枚举border显然可以用SAM来实现
    然后考虑贡献怎么计算
    简单推到即可发现
    对于SAM上任意一个节点(x)
    其贡献为

    [egin{align*} ans&=sum_{len=a}^bsum_{r=1}^{cnt[x]} sum_{l=1}^r frac{w_{pos}}{w_{pos-len}} \ &=frac{cnt_x*(cnt_x+1)}{2}*sum_{len=a}^bfrac{w_{pos}}{w_{pos-len}} \ &=frac{cnt_x*(cnt_x+1)}{2}*{w_{pos}}*sum_{len=a}^bfrac{1}{w_{pos-len}} end{align*} ]

    对于w数组的倒数搞一个前缀和即可

    #include<bits/stdc++.h>
    #define N 1100000
    #define db double
    #define ll long long
    #define ldb long double
    #define ull unsigned long long
    using namespace std;
    const int h=3,ki=149,mo=1e9+7;
    int mod(int x){return (x%mo+mo)%mo;}
    int inc(int x,int k){x+=k;return x<mo?x:x-mo;}
    int dec(int x,int k){x-=k;return x>=0?x:x+mo;}
    int ksm(int x,int k)
    {
    	int ans=1;
    	while(k){if(k&1)ans=1ll*ans*x%mo;k>>=1;x=1ll*x*x%mo;}
    	return mod(ans);
    }
    int inv(int x){return ksm(x,mo-2);}
    int read()
    {
    	char ch=0;int x=0,flag=1;
    	while(!isdigit(ch)){ch=getchar();if(ch=='-')flag=-1;}
    	while(isdigit(ch)){x=(x<<3)+(x<<1)+ch-'0',ch=getchar();}
    	return x*flag;
    }
    void write(int x)
    {
    	if(!x)return (void)putchar(48);
    	if(x<0)putchar(45),x=-x;
    	int len=0,p[20];
    	while(x)p[++len]=x%10,x/=10;
    	for(int i=len;i>=1;i--)putchar(p[i]+48);
    }
    const db eps=1e-7,inf=1e9+7,pi=acos(-1);
    db Read(){db x;scanf("%lf",&x);return x;}
    void Write(db x){printf("%lf",x);}
    char ch[N];
    int root=1,size=1,last=1,sz[N];
    struct node{int pos,len,lnk,nxt[26];}s[N];
    void insert(int k)
    {
        int cur=++size,p=last;last=cur;
       	sz[cur]=1;s[cur].pos=s[cur].len=s[p].len+1;
        while(p&&!s[p].nxt[k])s[p].nxt[k]=cur,p=s[p].lnk;
        if(!p){s[cur].lnk=root;return;}
        int q=s[p].nxt[k];
        if(s[p].len+1==s[q].len)s[cur].lnk=q;
        else
        {
            int clone=++size;
            s[clone]=s[q];s[clone].len=s[p].len+1;
            while(p&&s[p].nxt[k]==q)s[p].nxt[k]=clone,p=s[p].lnk;
            s[q].lnk=s[cur].lnk=clone;
        }
    }
    struct edge{int to,nxt;}e[N];
    int num,head[N];
    void add(int x,int y){e[++num]={y,head[x]};head[x]=num;}
    void dfs(int x,int fa)
    {
    	for(int i=head[x];i!=-1;i=e[i].nxt)
    	{
    		int to=e[i].to;
    		if(to==fa)continue;
    		dfs(to,x);sz[x]+=sz[to];
    	}
    }
    int p[N],w[N],v[N];
    int main()
    {
    	scanf("%s",ch+1);
    	int n=strlen(ch+1),tot=0,ans=0;
    	for(int i=1;i<=n;i++)insert(ch[i]-'a');	
    	for(int i=0;i<26;i++)p[i]=read(),tot=inc(tot,p[i]);
    	for(int i=0;i<26;i++)p[i]=1ll*tot*inv(p[i])%mo;
    	w[0]=1;for(int i=1;i<=n;i++)w[i]=1ll*w[i-1]*p[ch[i]-'a']%mo;
    	v[0]=1;for(int i=1;i<=n;i++)v[i]=inc(v[i-1],inv(w[i]));
    	num=-1;memset(head,-1,sizeof(head));
    	for(int x=2;x<=size;x++)add(s[x].lnk,x);dfs(1,1);
    	for(int x=2;x<=size;x++)
    	{
    		int a=s[s[x].lnk].len+1,b=s[x].len;
    		int l=s[x].pos-b,r=s[x].pos-a;
    		int t=1ll*(sz[x]+1)*sz[x]%mo*inv(2)%mo*w[s[x].pos]%mo; 
    		if(r>=0)ans=inc(ans,1ll*t*v[r]%mo);
    		if(l-1>=0)ans=dec(ans,1ll*t*v[l-1]%mo);
    	}
    	write(ans);
    	return 0;
    }
    
  • 相关阅读:
    ABAP 程序中的类 沧海
    ABAP类的方法(转载) 沧海
    More than 100 ABAP Interview Faq's(2) 沧海
    SAP and ABAP Memory总结 沧海
    ABAP Frequently Asked Question 沧海
    ABAP System Reports(Additional functions) 沧海
    ABAP Questions Commonly Asked 1 沧海
    ABAP Tips and Tricks 沧海
    ABAP System Fields 沧海
    ABAP 面试问题及答案(一):数据库更新及更改 SAP Standard (转) 沧海
  • 原文地址:https://www.cnblogs.com/Creed-qwq/p/14100040.html
Copyright © 2011-2022 走看看