21杭电多校第八场

A

数位\(dp\) 咕了

B

由于\(m\)很小,考虑用生成函数表示方案数,设\(f_i\)表示\(i\)个物品的生成函数

转移\(f_i\)时,单独考虑第\(i\)个物品有三种情况\((不选,s,b)\),对应价格为\((0,1,2)\),贡献为\(f_{i-1}(1+x+x^2)\)

否则\(i\)\(i-1\)联合考虑,一共四种情况\((ss,sb,bs,ss)\),对应价格为\((1,2,2,3)\),贡献为\(f_{i-2}(x+2x^2+x^3)\)

得到了这个生成函数的递推式,可以用矩阵加速,即:

\[\begin{bmatrix} f_i\\f_{i-1} \end{bmatrix} = \begin{pmatrix} 1+x+x^2&x+2x^2+x^3\\1&0 \end{pmatrix} \begin{bmatrix} f_{i-1}\\f_{i-2} \end{bmatrix} \]

\(ntt\)与矩阵快速幂解决,每次卷积后只保留前\(m+1\)项即可

暴力卷积的话矩阵乘法需要\(16\)\(dft\)\(8\)\(idft\)

考虑一些优化,有一些重复的\(dft\)可以避免,矩阵乘法中的相加用点值同样可以做到

因此普通乘法只需要\(8\)\(dft\)\(4\)\(idft\)即可做到

而快速幂中两个矩阵相等,可以把\(dft\)优化到\(4\)

#include<bits/stdc++.h>
#define inf 2139062143
#define ll long long
#define db double
#define ld long double
#define ull unsigned long long
#define MAXN 70100
#define MOD 998244353
#define Fill(a,x) memset(a,x,sizeof(a))
#define rep(i,s,t) for(int i=(s),i##end=(t);i<=i##end;++i)
#define dwn(i,s,t) for(int i=(s),i##end=(t);i>=i##end;--i)
#define ren for(int i=fst[x];i;i=nxt[i])
#define pls(a,b) (a+b)%MOD
#define mns(a,b) (a-(b))%MOD
#define mul(a,b) (1LL*(a)*(b))%MOD
#define pii pair<int,int>
#define fi first
#define se second
#define pb push_back
using namespace std;
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
    while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
int n,mxm,rev[MAXN],lim,lg,pw[20],ipw[20];
int qp(int x,int t,int res=1)
{
    for(;t;t>>=1,x=mul(x,x)) if(t&1) res=mul(res,x);
    return res;
}
#define inv(x) qp(x,MOD-2)
int mem(int n)
{
    int lg=1,lim=1;
    for(;lim<n;lim<<=1,lg++)
        pw[lg]=qp(3,(MOD-1)/(1<<lg)),ipw[lg]=inv(pw[lg]);
    rep(i,0,lim-1) rev[i]=(rev[i>>1]>>1)|((i&1)<<(lg-2));
    return lim;
}
struct Poly
{
    int a[MAXN],len;
    void clear(){Fill(a,0);}
    void init(int *x,int n){len=n;rep(i,0,n-1) a[i]=x[i];}
    void ntt(int n,int f)
    {
        rep(i,0,n-1) if(i<rev[i]) swap(a[i],a[rev[i]]);
        for(int i=1,t=1;i<n;i<<=1,++t)
        {
            int wn= f>0?pw[t]:ipw[t];for(int j=0;j<n;j+=i<<1)
            {
                int w=1,x,y;for(int k=0;k<i;++k,w=mul(w,wn))
                    x=a[j+k],y=mul(a[j+k+i],w),a[j+k]=pls(x,y),a[j+k+i]=mns(x,y);
            }
        }
        rep(i,0,n-1) a[i]=pls(a[i],MOD);if(f>0) return ;
        int nv=inv(n);rep(i,0,n-1) a[i]=mul(a[i],nv);
    }
    void dft(int n){len=n;ntt(len,1);}
    void idft(){ntt(len,-1);dwn(i,len-1,mxm+1) a[i]=0;len=min(len,mxm+1);}
    void print(int n,int st){rep(i,st,n-1) printf("%d ",a[i]);puts("");}
};
Poly operator + (Poly x,Poly y)
{
    static Poly res;res.clear();res.len=max(y.len,x.len);
    rep(i,0,res.len-1) res.a[i]=pls(x.a[i],y.a[i]);
    return res;
}
Poly operator * (Poly x,Poly y)
{
    static Poly res;res.clear();res.len=max(y.len,x.len);
    rep(i,0,res.len-1) res.a[i]=mul(y.a[i],x.a[i]);
    return res;
}
struct mat
{
    int n,m;Poly p[2][2];
    void init(int N,int M)
	{
		n=N,m=M;
		rep(i,0,n-1) rep(j,0,m-1)
			{p[i][j].len=1;Fill(p[i][j].a,0);}
	}
    mat sqr()
    {
        int mx=0;static mat res;res.init(n,m);
        rep(i,0,n-1) rep(j,0,m-1) mx=max(mx,p[i][j].len);
        mx=mx*2-1;mx=mem(mx);
        rep(i,0,n-1) rep(j,0,m-1) p[i][j].dft(mx);
        rep(i,0,n-1) rep(j,0,m-1) rep(k,0,n-1)
            res.p[i][j]=res.p[i][j]+(p[i][k]*p[k][j]);
        rep(i,0,n-1) rep(j,0,m-1) res.p[i][j].idft();
        return res;
    }
};
mat operator * (mat a,mat b)
{
    int m1=0,m2=0;
    static mat res;res.init(a.n,b.m);
	rep(i,0,a.n-1) rep(j,0,a.m-1) m1=max(m1,a.p[i][j].len);
    rep(i,0,b.n-1) rep(j,0,b.m-1) m2=max(m2,b.p[i][j].len);
    m1=m1+m2-1;m1=mem(m1);
    rep(i,0,a.n-1) rep(j,0,a.m-1) a.p[i][j].dft(m1);
    rep(i,0,b.n-1) rep(j,0,b.m-1) b.p[i][j].dft(m1);
    rep(i,0,a.n-1) rep(j,0,b.m-1) rep(k,0,a.m-1)
        {res.p[i][j]=res.p[i][j]+(a.p[i][k]*b.p[k][j]);}
    rep(i,0,a.n-1) rep(j,0,b.m-1) res.p[i][j].idft();
    return res;
}
mat qp(mat x,int t)
{
    static mat res;res.init(x.n,x.m);
	rep(i,0,n-1) res.p[i][i].a[0]=1;
    for(;t;t>>=1,x=x.sqr()) {if(t&1) res=res*x;}
    return res;
}
int g[5];
int main()
{
    mat bas,x,f,y;bas.init(2,2),x.init(2,2),f.init(2,1),y.init(2,1);
    bas.p[1][1].init(g,1);
    g[0]=1;bas.p[1][0].init(g,1);f.p[1][0].init(g,1);
    g[1]=g[2]=1;bas.p[0][0].init(g,3);f.p[0][0].init(g,3);
    g[0]=0,g[1]=g[3]=1,g[2]=2;bas.p[0][1].init(g,4);
    rep(T,1,read())
    {
        n=read(),mxm=read();
        x=qp(bas,n-1);y=x*f;
        y.p[0][0].print(mxm+1,1);
    }
}

C

使用\(Prim\)算法求最小生成树,复杂度\(O(n^2)\)

#include<bits/stdc++.h>
#define ll long long
#define db double
#define ld long double
#define ull unsigned long long
#define MAXN 2500100
#define MOD 998244353
#define Fill(a,x) memset(a,x,sizeof(a))
#define rep(i,s,t) for(register int i=(s),i##end=(t);i<=i##end;++i)
#define dwn(i,s,t) for(register int i=(s),i##end=(t);i>=i##end;--i)
#define ren for(int i=fst[x];i;i=nxt[i])
#define pls(a,b) (a+b)%MOD
#define mns(a,b) (a-b+MOD)%MOD
#define mul(a,b) (1LL*(a)*(b))%MOD
#define pii pair<int,int>
#define fi first
#define se second
#define pb push_back
using namespace std;
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
    while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
int n,x[5050],y[5050],frm[5050];ll low[5050],e[5050][5050];
inline ll sqr(ll x){return x*x;}
inline ll dis(int i,int j){return sqr(x[i]-x[j])+sqr(y[i]-y[j]);}
const ll inf=9e18;
ll prim()
{
    rep(i,1,n) low[i]=e[1][i],frm[i]=1;
    frm[1]=-1;ll mx=0,mn;int v;
	rep(i,2,n)
    {
		v=-1;mn=inf;
		rep(j,1,n) if(~frm[j]&&low[j]<mn) v=j,mn=low[j];
		if(v==-1) continue;
		frm[v]=-1,mx=max(low[v],mx);
		rep(j,1,n) if(~frm[j]&&low[j]>e[v][j])
			low[j]=e[v][j],frm[j]=v;
    }
    return mx;
}
int main()
{
    rep(T,1,read())
    {
        scanf("%d",&n);
        rep(i,1,n) x[i]=read(),y[i]=read();
        rep(i,1,n) rep(j,i,n)
			if(i==j) e[i][j]=0;
			else e[i][j]=e[j][i]=dis(i,j);
		printf("%lld\n",prim());
    }
}

D

两个修改操作分别相当于减少二进制上最小的\(1\)以及把最高位的\(1\)左移一位

因为\(1\)的数量不会改变,因此最多减小\(31\)次后数就会变成\(0\)

可以把最高位的\(1\)用线段树维护,相当于支持区间乘二,区间和查询以及单点置零

对于其余位的\(1\)暴力维护,用树状数组单点修改,区间查询;再用并查集+链表维护已经被置零的数

#include<bits/stdc++.h>
#define inf 2139062143
#define ll long long
#define db double
#define ld long double
#define ull unsigned long long
#define MAXN 100100
#define MOD 998244353
#define Fill(a,x) memset(a,x,sizeof(a))
#define rep(i,s,t) for(int i=(s),i##end=(t);i<=i##end;++i)
#define dwn(i,s,t) for(int i=(s),i##end=(t);i>=i##end;--i)
#define ren for(int i=fst[x];i;i=nxt[i])
#define pls(a,b) (a+b)%MOD
#define mns(a,b) (a-(b))%MOD
#define mul(a,b) (1LL*(a)*(b))%MOD
#define pii pair<int,int>
#define fi first
#define se second
#define pb push_back
using namespace std;
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
    while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
inline void inc(int &x,int y){x=pls(x,y);}
inline void tms(int &x,int y){x=mul(x,y);}
int n,g[MAXN],h[MAXN],fa[MAXN],sum[MAXN<<2],tag[MAXN<<2],isz[MAXN<<2],c[MAXN];
void add(int x,int w){for(;x<=n;x+=x&-x) inc(c[x],w);}
int pres(int x,int res=0){for(;x;x-=x&-x) inc(res,c[x]);return res;}
int gets(int l,int r){return mns(pres(r),pres(l-1));}
int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}
inline void upd(int k)
{
	sum[k]=pls(sum[k<<1],sum[k<<1|1]);
	isz[k]=isz[k<<1]&isz[k<<1|1];
}
inline void pshd(int k)
{
	tms(sum[k<<1],tag[k]);tms(sum[k<<1|1],tag[k]);
	tms(tag[k<<1],tag[k]);tms(tag[k<<1|1],tag[k]);
	tag[k]=1;
}
void build(int k,int l,int r)
{
	tag[k]=1;if(l==r) {sum[k]=g[l],isz[k]=0;return ;}int mid=l+r>>1;
	build(k<<1,l,mid);build(k<<1|1,mid+1,r);upd(k);
}
void mdf(int k,int l,int r,int a,int b)
{
	if(isz[k]) return ;if(a<=l&&r<=b) {tms(sum[k],2);tms(tag[k],2);return ;}
	int mid=l+r>>1;if(tag[k]!=1) pshd(k);
	if(a<=mid) mdf(k<<1,l,mid,a,b);
	if(b>mid) mdf(k<<1|1,mid+1,r,a,b);
	upd(k);
}
void dec(int k,int l,int r,int x)
{
	if(l==r) {isz[k]=1,sum[k]=0;return ;}
	int mid=l+r>>1;if(tag[k]!=1) pshd(k);
	x<=mid?dec(k<<1,l,mid,x):dec(k<<1|1,mid+1,r,x);
	upd(k);
}
int query(int k,int l,int r,int a,int b)
{
	if(isz[k]) return 0;if(a<=l&&r<=b) return sum[k];
	int mid=l+r>>1,res=0;if(tag[k]!=1) pshd(k);
	if(a<=mid) res=query(k<<1,l,mid,a,b);
	if(b>mid) inc(res,query(k<<1|1,mid+1,r,a,b));return res;
}
void work(int l,int r)
{
	for(int tmp;l<=r;l++)
	{
		l=find(l);if(l>r) break;
		if(h[l]>0) {tmp=h[l]&-h[l];add(l,-tmp);h[l]-=tmp;}
		else if(!h[l]) {dec(1,1,n,l);h[l]=-1,fa[l]=l+1;}
	}
}
int main()
{
	int t,a,b,x;
	rep(T,1,read())
	{
		n=read();rep(i,1,n)
		{
			scanf("%d",&g[i]);fa[i]=i;
			for(x=g[i];x!=(x&-x);x-=x&-x);
			h[i]=g[i]-x;add(i,g[i]-x);g[i]=x;
		}
		build(1,1,n);fa[n+1]=n+1;
		rep(Q,1,read())
		{
			scanf("%d%d%d",&t,&a,&b);
			if(t==1) printf("%d\n",pls(pls(gets(a,b),query(1,1,n,a,b)),MOD));
			else if(t==2) work(a,b);
			else mdf(1,1,n,a,b);
		}
		rep(i,1,n) if(h[i]>0) add(i,-h[i]);
	}
}

E

考虑每一位的贡献,题目相当于在\(n-1\)个空位里插\(\le k-1\)个板,枚举这一位之后的板插在哪里或不插,答案为:

\[\begin{aligned} ans&=\sum\limits_{x=0}^k\sum\limits_{i=1}^na_i\lgroup \sum\limits_{j=0}^{n-i-1}10^j\binom{n-2-j}{x-1}+10^{n-i}\binom{i-1}{x}\rgroup\\ &=\sum\limits_{i=1}^na_i\lgroup\sum\limits_{j=0}^{n-i-1}10^j\sum\limits_{x=0}^{k-1}\binom{n-2-j}{x}+10^{n-i}\sum\limits_{x=0}^k\binom{i-1}{x}\rgroup \end{aligned} \]

注意到两个组合数求和都是对每一行求一段连续固定长度的和,则可以算出第一行后直接递推

处理出\(sum_i=\sum\limits_{j=0}^{k-1}\binom{i}{j}\)后,前半部分即为\(\sum\limits_{j=0}^{n-i-1}10^jsum_{n-2-j}\),也很容易递推

#include<bits/stdc++.h>
#define inf 2139062143
#define ll long long
#define db double
#define ld long double
#define ull unsigned long long
#define MAXN 1001001
#define MOD 998244353
#define Fill(a,x) memset(a,x,sizeof(a))
#define rep(i,s,t) for(int i=(s),i##end=(t);i<=i##end;++i)
#define dwn(i,s,t) for(int i=(s),i##end=(t);i>=i##end;--i)
#define ren for(int i=fst[x];i;i=nxt[i])
#define pls(a,b) (a+b)%MOD
#define mns(a,b) (a-(b)+MOD)%MOD
#define mul(a,b) (1LL*(a)*(b))%MOD
#define pii pair<int,int>
#define fi first
#define se second
#define pb push_back
using namespace std;
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
    while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
int k,n,m,fac[MAXN],ifac[MAXN],ans,pw10[MAXN];
int f[MAXN],g[MAXN],s[MAXN];char ch[MAXN];
int q_pow(int bas,int t,int res=1)
{
    for(;t;t>>=1,bas=mul(bas,bas)) if(t&1) res=mul(res,bas);return res;
}
#define inv(x) q_pow(x,MOD-2)
inline int C(int n,int m)
{
	if(m<0||n<m) return 0;
	return mul(fac[n],mul(ifac[m],ifac[n-m]));
}
void mem(int n=1e6)
{
	fac[0]=ifac[0]=pw10[0]=1;
	rep(i,1,n) fac[i]=mul(fac[i-1],i),pw10[i]=mul(pw10[i-1],10);
	ifac[n]=inv(fac[n]);
	dwn(i,n-1,1) ifac[i]=mul(ifac[i+1],i+1);
}
ll Force(ll ans=0,ll res=0)
{
	rep(x,0,k) rep(i,1,n)
	{
		res=0;
		rep(j,0,n-i-1) res=pls(res,mul(C(n-2-j,x-1),pw10[j]));
		res=pls(res,mul(pw10[n-i],C(i-1,x)));
		res=mul(res,g[i]),ans=pls(ans,res);
	}
	return ans;
}
int main()
{
	int res,tmp;mem();
	rep(T,1,read())
	{
		k=read()-1;scanf("%s",ch+1);n=strlen(ch+1);
		rep(i,1,n) g[i]=ch[i]-'0';ans=0;tmp=1;
		//cout<<Force()<<endl;
		rep(i,1,n)
			res=mul(tmp,mul(g[i],pw10[n-i])),ans=pls(ans,res),
			tmp=mul(tmp,2),tmp=mns(tmp,C(i-1,k));
		if(!k) {printf("%d\n",ans);continue;}
		f[0]=tmp=1;rep(i,1,n)
			tmp=mul(tmp,2),tmp=mns(tmp,C(i-1,k-1)),f[i]=tmp;
		rep(i,0,n-2) s[i]=mul(pw10[i],f[n-2-i]);
		rep(i,1,n-2) s[i]=pls(s[i],s[i-1]);
		rep(i,1,n) ans=pls(ans,mul(g[i],s[n-i-1]));
		printf("%d\n",ans);
	}
}

F

对于每个数,每次操作相当于除一些质因数

\(f[i]\)表示\(i\)这个数质数分解后的质数幂次之和,则原题相当于对一些石子数量为\(f[a_i]\)的石子做\(nim\)博弈

线性筛预处理\(f_i\)

#include<bits/stdc++.h>
#define inf 2139062143
#define ll long long
#define db double
#define ld long double
#define ull unsigned long long
#define MAXN 10010010
#define MOD 998244353
#define Fill(a,x) memset(a,x,sizeof(a))
#define rep(i,s,t) for(int i=(s),i##end=(t);i<=i##end;++i)
#define dwn(i,s,t) for(int i=(s),i##end=(t);i>=i##end;--i)
#define ren for(int i=fst[x];i;i=nxt[i])
#define pls(a,b) (a+b)%MOD
#define mns(a,b) (a-(b)+MOD)%MOD
#define mul(a,b) (1LL*(a)*(b))%MOD
#define pii pair<int,int>
#define fi first
#define se second
#define pb push_back
using namespace std;
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
    while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
int ntp[MAXN],f[MAXN],p[MAXN/7],tot,n,ans;
void mem(int n=1e7)
{
	rep(i,2,n)
	{
		if(!ntp[i]) p[++tot]=i,f[i]=1;
		rep(j,1,tot) if(i*p[j]>n) break;
			else {ntp[i*p[j]]=1,f[i*p[j]]=f[i]+1;if(i%p[j]==0) break;}
	}
}
int main()
{
	mem();rep(T,1,read())
	{
		n=read();rep(i,1,n) ans^=f[read()];
		puts(ans?"Alice":"Bob");ans=0;
	}
}

G

线段树 咕

H

对于一个正方形和圆来说,正方形能够被圆完全包含的中心位置也形成一个圆

题目转化为两个圆面积求交

特判一下圆\(B\)无法包含正方形以及两个圆包含相离的情况

#include<bits/stdc++.h>
#define inf 2139062143
#define ll long long
#define db double
#define ld long double
#define ull unsigned long long
#define MAXN 100100
#define MOD 998244353
#define Fill(a,x) memset(a,x,sizeof(a))
#define rep(i,s,t) for(int i=(s),i##end=(t);i<=i##end;++i)
#define dwn(i,s,t) for(int i=(s),i##end=(t);i>=i##end;--i)
#define ren for(int i=fst[x];i;i=nxt[i])
#define pls(a,b) (a+b)%MOD
#define mns(a,b) (a-(b)+MOD)%MOD
#define mul(a,b) (1LL*(a)*(b))%MOD
#define pii pair<int,int>
#define fi first
#define se second
#define pb push_back
using namespace std;
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
    while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
const db pi=acos(-1);
db r1,r2,d,len;
struct Point{db x,y;}a,b;
inline db sqr(db x){return x*x;}
inline db dis(Point a,Point b){return sqrt(sqr(a.x-b.x)+sqr(a.y-b.y));}
db solve()
{
	db d=dis(a,b);
	if(d>=r1+r2) return 0.0;
	if(d<=r1-r2) return pi*r2*r2;
	if(d<=r2-r1) return pi*r1*r1;
	db p=(r1+r2+d)/2.0;
    db a1=acos((r1*r1+d*d-r2*r2)/(2.0*r1*d));
    db a2=acos((r2*r2+d*d-r1*r1)/(2.0*r2*d));
    return a1*r1*r1+a2*r2*r2-2.0*sqrt(p*(p-r1)*(p-r2)*(p-d));
}
int main()
{
	rep(T,1,read())
	{
		cin>>r1>>a.x>>a.y>>r2>>b.x>>b.y>>len;
		if(len*len>=r2*r2*2) {puts("0.000000");continue;}
		r1=sqrt(sqr(r1)-sqr(len/2))-len/2;
		r2=sqrt(sqr(r2)-sqr(len/2))-len/2;
		printf("%.6lf\n",solve()/(pi*r1*r1));
	}
}

I

因为模式串的长度不超过\(30\),可以用字符串哈希暴力算出母串所有长度不超过\(30\)的子串的答案

每次\(check\)所有模式串即可

#include<bits/stdc++.h>
#define inf 2139062143
#define ll long long
#define db double
#define ld long double
#define ull unsigned long long
#define MAXN 400100
#define MOD 998244353
#define Fill(a,x) memset(a,x,sizeof(a))
#define rep(i,s,t) for(int i=(s),i##end=(t);i<=i##end;++i)
#define dwn(i,s,t) for(int i=(s),i##end=(t);i>=i##end;--i)
#define ren for(int i=fst[x];i;i=nxt[i])
#define pls(a,b) (a+b)%MOD
#define mns(a,b) (a-(b)+MOD)%MOD
#define mul(a,b) (1LL*(a)*(b))%MOD
#define pii pair<int,int>
#define Clear(x) {x.clear();vector<pii> (x).swap(x);}
#define fi first
#define se second
#define pb push_back
using namespace std;
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
    while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
const int mod=998244353,bas=137;
int n,m,len,p[MAXN],res[MAXN],ans[MAXN];
char ch[MAXN],cc[40];
int w1[MAXN],w2[MAXN],val[MAXN];
vector<pii> vec[40];map<int,int> mp;
int hsh[MAXN],pw[MAXN];
inline int calc(int l,int r)
{
	return (hsh[r]-(1LL*hsh[l-1]*pw[r-l+1])%mod+mod)%mod;
}
void work(int x)
{
	int tmp,tot=0;
	rep(i,1,m-x+1)
	{
		tmp=calc(i,i+x-1),w1[i]=tmp;
		if(!mp[w1[i]]) mp[w1[i]]=++tot,w2[i]=tot;
		else w2[i]=mp[w1[i]];
	}
	rep(i,1,tot) p[i]=-m,res[i]=0;
	rep(i,1,m-x+1) if(p[w2[i]]<=i-x) res[w2[i]]++,p[w2[i]]=i;
	for(auto t:vec[x])
	{
		tmp=t.se;
		if(!mp.count(tmp)) ans[t.fi]=0;
		else ans[t.fi]=res[mp[tmp]];
	}
	Clear(vec[x]);mp.clear();
}
int main()
{
	int h1;rep(T,1,read())
	{
		scanf("%s",ch+1);m=strlen(ch+1);pw[0]=1;
		rep(i,1,m)
        	pw[i]=(1LL*pw[i-1]*bas)%mod,hsh[i]=((1LL*hsh[i-1]*bas)%mod+ch[i]-'a'+1)%mod;
		n=read();rep(i,1,n)
		{
			scanf("%s",cc+1);len=strlen(cc+1);h1=0;
			rep(i,1,len)
				h1=((1LL*h1*bas)%mod+cc[i]-'a'+1)%mod;
			vec[len].pb({i,h1});
		}
		rep(i,1,30) if(vec[i].size()) work(i);
		rep(i,1,n) printf("%d\n",ans[i]);
	}
}

J

连通性\(dp\)

posted @ 2021-08-12 21:27  jack_yyc  阅读(43)  评论(0编辑  收藏  举报