H(dp计数)
题意:
有一颗树,最深的点的深度是n,每个深度为i的点都有ai个孩子。
对于1<=k<=2n-2,回答树上有多少点对之间的距离是k,答案对1e9+7取模
n<=5000,ai<=1e9
分析:
考虑在lca处计数,发现时间复杂度是O(n^3),即使用卷积优化也仍旧是O(n^2logn)的,无法通过n=5000的情况
考虑另一种计数方式,在端点处计数,分为两种,一种是down,一种是up,down就比较好处理,至于up考虑根据上一个深度来dp
考虑up的时候只有两种决策,一种是挂一个下来,另一种是在当前深度的上一个进行转弯,分别计数即可
时间复杂度O(n^2)
G(FFT+dsu)
题意:
我们定义两个等长字符串x和y的距离就是将最少的字母让另一种字母替代,使得x=y
现在给出两个字符串S,T,|S|>=|T|,问S的所有长度为T的子串,每个子串和T的距离分别是多少,都要输出
|S|<=125000
字符集只有abcdef
分析:
考虑如何求两个等长字符串的距离,我们只需要给对应字母建个无向图,答案就是点数-连通块个数
因为字符集很小,只有abcdef,所以连边情况只有36种,可以状态压缩
我们可以枚举s中的某个字母a,t中的某个字母b,看看有哪些位置的S子串会被这个(a,b)贡献到
这个东西可以用卷积来实现
把s中a的对应位置抠出来赋值为1,其它为0,把t中b的对应位置抠出来赋值为1,其它为0,两个多项式卷积一下就行了
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int maxn=5e5; 4 const double pi=acos(-1.0); 5 char t[maxn+5],s[maxn+5]; 6 int id[6][6]; 7 pair<int,int> index[36]; 8 long long state[maxn+5]; 9 int n,m; 10 struct wjmzbmr 11 { 12 double r,i; 13 wjmzbmr(double real=0.0,double image=0.0){r=real;i=image;} 14 wjmzbmr operator + (const wjmzbmr o) 15 { 16 return wjmzbmr(r+o.r,i+o.i); 17 } 18 wjmzbmr operator - (const wjmzbmr o) 19 { 20 return wjmzbmr(r-o.r,i-o.i); 21 } 22 wjmzbmr operator * (const wjmzbmr o) 23 { 24 return wjmzbmr(r*o.r-i*o.i,r*o.i+i*o.r); 25 } 26 }; 27 wjmzbmr x1[maxn+5],x2[maxn+5]; 28 void brc(wjmzbmr *y,int l) 29 { 30 for(int i=1,j=l/2;i<l-1;i++) 31 { 32 if(i<j) swap(y[i],y[j]); 33 int k=l/2; 34 while(j>=k)j-=k,k/=2; 35 if(j<k) j+=k; 36 } 37 } 38 void fft(wjmzbmr *y,int l,double on) 39 { 40 wjmzbmr u,t; 41 brc(y,l); 42 for(int h=2;h<=l;h<<=1) 43 { 44 wjmzbmr wn(cos(on*2*pi/h),sin(on*2*pi/h)); 45 for(int j=0;j<l;j+=h) 46 { 47 wjmzbmr w(1,0); 48 for(int k=j;k<j+h/2;k++) 49 { 50 u=y[k]; 51 t=w*y[k+h/2]; 52 y[k]=u+t; 53 y[k+h/2]=u-t; 54 w=w*wn; 55 } 56 } 57 } 58 if(on==-1)for(int i=0;i<l;i++) y[i].r/=l; 59 } 60 void work(int x,int y) 61 { 62 int len=1; 63 while(len<n+m) len<<=1; 64 for(int i=0;i<=len;++i) x1[i].r=x1[i].i=x2[i].i=x2[i].r=0.0; 65 for(int i=0;i<n;++i) if(s[i]==x+‘a‘) x1[i].r=1; 66 for(int i=0;i<m;++i) if(t[i]==y+‘a‘) x2[i].r=1; 67 reverse(x2,x2+m); 68 fft(x1,len,1); 69 fft(x2,len,1); 70 for(int i=0;i<len;++i) x1[i]=x1[i]*x2[i]; 71 fft(x1,len,-1); 72 for(int i=0;i<n;++i) 73 if((int)(x1[i+m-1].r+0.5)>0) state[i]|=(1LL<<id[x][y]); 74 } 75 int f[6]; 76 int find(int x) 77 { 78 if(f[x]==x) return x; 79 else return f[x]=find(f[x]); 80 } 81 void uni(int x,int y) 82 { 83 int u=find(x),v=find(y); 84 if(u==v) return ; 85 f[u]=v; 86 } 87 int cal(long long s) 88 { 89 for(int i=0;i<6;++i) f[i]=i; 90 for(int i=0;i<36;++i) 91 if(s&(1LL<<i)) 92 { 93 int u=index[i].first,v=index[i].second; 94 uni(u,v); 95 } 96 int ans=6; 97 for(int i=0;i<6;++i) 98 if(f[i]==i) --ans; 99 return ans; 100 } 101 int main() 102 { 103 scanf("%s%s",s,t); 104 n=strlen(s),m=strlen(t); 105 int sz=0; 106 for(int i=0;i<6;++i) 107 for(int j=0;j<6;++j) 108 { 109 id[i][j]=sz; 110 index[sz]=make_pair(i,j); 111 ++sz; 112 } 113 for(int i=0;i<6;++i) 114 for(int j=0;j<6;++j) 115 if(i!=j) 116 work(i,j); 117 for(int i=0;i<=n-m;++i) 118 printf("%d ",cal(state[i])); 119 return 0; 120 }
原文地址:https://www.cnblogs.com/wmrv587/p/8671968.html
时间: 2024-11-09 03:06:24