\(A\)
咕咕
const int N=5e5+5; char s[N];int res,n,sum; int main(){ scanf("%s",s+1),res=n=strlen(s+1); fp(i,1,n)if(s[i]=='S')++sum; else if(sum)--sum,res-=2; printf("%d\n",res); return 0; }
\(B\)
咕咕
//quming #include<bits/stdc++.h> #define R register #define fp(i,a,b) for(R int i=(a),I=(b)+1;i<I;++i) #define fd(i,a,b) for(R int i=(a),I=(b)-1;i>I;--i) #define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v) template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,1:0;} template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;} using namespace std; typedef long long ll; const int N=2e5+5,inf=0x3f3f3f3f; int a[N],l[N],r[N],st[N],n,top;ll res; int main(){ scanf("%d",&n); fp(i,1,n)scanf("%d",&a[i]); a[0]=a[n+1]=0,st[++top]=0; fp(i,1,n){ while(top&&a[i]<a[st[top]])--top; l[i]=st[top],st[++top]=i; } st[top=1]=n+1; fd(i,n,1){ while(top&&a[i]<a[st[top]])--top; r[i]=st[top],st[++top]=i; } fp(i,1,n)res+=1ll*a[i]*(i-l[i])*(r[i]-i); printf("%lld\n",res); return 0; }
\(C\)
因为树上所有直径有同一个中点或同一条中边,那么\(dis\)最小的点只能有\(1\)个或者两个
然后我们从中点开始构造一条直径,如果无法构造出无解,否则剩下的点都可以挂在直径上而满足条件
最后判一下构造出的直径是否满足它给出的\(dis\)即可
const int N=105; int c[N],n,mn=233,mx; int main(){ scanf("%d",&n); for(R int i=1,x;i<=n;++i)scanf("%d",&x),++c[x],cmin(mn,x),cmax(mx,x); if(c[mn]>2)return puts("Impossible"),0; fp(i,mn+1,mx)if(c[i]<2)return puts("Impossible"),0; if(c[mn]==2&&mn!=mx-mn+1)return puts("Impossible"),0; if(c[mn]==1&&mn!=mx-mn)return puts("Impossible"),0; return puts("Possible"),0; }
\(D\)
这种题目显然是容斥了
然而如果直接枚举有几个点选了不该选的数会有问题,因为有的点选不该选的数有两种方案,有的点选了别的点就不能选
发现选了之后\(i\)只会影响\(...,i-4k,i-2k,i+2k,i+4k,...\)的数的选法,那么我们把所有模\(2k\)意义下相等的位置一起考虑,记\(f_{i,j,0/1/2}\)表示考虑到这一类中的第\(i\)个数,选了其中\(j\)个,第\(i\)个数不选\(/\)选择在这个位置放\(i-k/\)选择在这个位置放\(i+k\)的方案数,转移即可,最后暴力加到全局的背包里,即可计算出\(s[i]\)表示至少有这\(i\)个位置选择不合法的方案数,就可以直接套容斥了
//quming #include<bits/stdc++.h> #define R register #define fp(i,a,b) for(R int i=(a),I=(b)+1;i<I;++i) #define fd(i,a,b) for(R int i=(a),I=(b)-1;i>I;--i) #define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v) template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,1:0;} template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;} using namespace std; const int P=924844033; inline void upd(R int &x,R int y){(x+=y)>=P?x-=P:0;} inline int add(R int x,R int y){return x+y>=P?x+y-P:x+y;} inline int dec(R int x,R int y){return x-y<0?x-y+P:x-y;} inline int mul(R int x,R int y){return 1ll*x*y-1ll*x*y/P*P;} int ksm(R int x,R int y){ R int res=1; for(;y;y>>=1,x=mul(x,x))(y&1)?res=mul(res,x):0; return res; } const int N=2005; int n,k,res,len,f[N][3],g[N][3],s[N],t[N],fac[N]; void calc(R int x){ memset(f,0,sizeof(f)); f[0][0]=1; R int p=0; for(;x<=n;x+=(k<<1)){ fp(i,0,p){ g[i][0]=f[i][0],g[i][1]=f[i][1],g[i][2]=f[i][2]; f[i][0]=f[i][1]=f[i][2]=0; } fp(i,0,p){ R int s=add(g[i][0],add(g[i][1],g[i][2])); upd(f[i][0],s); if(x>k)upd(f[i+1][1],dec(s,g[i][2])); if(x+k<=n)upd(f[i+1][2],s); } ++p; } memset(t,0,sizeof(t)); fp(i,0,len)fp(j,0,p)upd(t[i+j],mul(s[i],add(f[j][0],add(f[j][1],f[j][2])))); len+=p; fp(i,0,len)s[i]=t[i]; } int main(){ // freopen("testdata.in","r",stdin); scanf("%d%d",&n,&k); fac[0]=1;fp(i,1,n)fac[i]=mul(fac[i-1],i); s[0]=1; fp(i,1,min(k<<1,n))calc(i); fp(i,0,len)upd(res,i&1?dec(0,mul(fac[n-i],s[i])):mul(fac[n-i],s[i])); printf("%d\n",res); return 0; }
\(E\)
博弈论菜鸡在此
首先如果存在一个情况,\(A\)在\(u\),\(B\)在\(v\),如果\(u\)能走到的任何一条边在蓝树上到\(v\)的距离都小于等于\(1\),\(A\)只能等死了,否则如果存在一条边\((u,v)\)满足蓝树上的距离大于\(2\),那么\(A\)就可以一直利用这条边绕\(B\)了,此时输出\(-1\)
如果会被追到,那么以蓝树上的\(Y\)为根,我们发现\(A\)根本走不出这棵子树,那么我们找到所有\(A\)能到达的点,然后到其中深度最大的点等死就行了
//quming #include<bits/stdc++.h> #define R register #define fp(i,a,b) for(R int i=(a),I=(b)+1;i<I;++i) #define fd(i,a,b) for(R int i=(a),I=(b)-1;i>I;--i) #define go(head,u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v) template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,1:0;} template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;} using namespace std; const int N=1e6+5; struct eg{int v,nx;}e[N<<1];int bl[N],rd[N],tot; inline void add(R int *head,R int u,R int v){e[++tot]={v,head[u]},head[u]=tot;} int fr[N],to[N],dep[N],fa[N],dfn[N],low[N],ok[N],vis[N],dis[N],tim,n,S,T; void dfs(int *head,int u){ dfn[u]=++tim; go(head,u)if(v!=fa[u])fa[v]=u,dep[v]=dep[u]+1,dfs(head,v); low[u]=tim; } inline bool ck(R int u,R int v){ if(dfn[u]>dfn[v])swap(u,v);if(low[u]>=low[v])return dep[v]-dep[u]>2; if(fa[u]==fa[v])return false;return true; } int q[N]; void bfs(){ int h=1,t=0,u;q[++t]=S,vis[S]=1; while(h<=t){ u=q[h++]; go(rd,u)if(!vis[v]){ dis[v]=dis[u]+1; if(dis[v]<dep[v])vis[v]=1,q[++t]=v; } } } int main(){ scanf("%d%d%d",&n,&S,&T); for(R int i=1,u,v;i<n;++i)scanf("%d%d",&u,&v),fr[i]=u,to[i]=v; for(R int i=1,u,v;i<n;++i)scanf("%d%d",&u,&v),add(bl,u,v),add(bl,v,u); dfs(bl,T); for(R int i=1,u,v;i<n;++i){ u=fr[i],v=to[i]; if(ck(u,v))ok[u]=ok[v]=1; else add(rd,u,v),add(rd,v,u); } bfs(); fp(i,1,n)if(vis[i]&&ok[i])return puts("-1"),0; R int res=0; fp(i,1,n)if(vis[i])cmax(res,dep[i]<<1); printf("%d\n",res); return 0; }
\(F\)
先考虑如何计算单个\(k\),那么对于每个点分别计算贡献,一个点会被计入贡献的次数是\({n\choose k}-\sum_{v\in son_u}{sz_v\choose k}\),其中\(sz_v\)表示以\(u\)为根时\(v\)子树的大小
那么\(n\)个点加起来就是\(n\times {n\choose k}-\sum_{i=1}^n cnt[i]\times {i\choose k}\),把组合数拆成阶乘的形式就可以把后面看成一个卷积了,\(NTT\)即可
//quming #include<bits/stdc++.h> #define R register #define fp(i,a,b) for(R int i=(a),I=(b)+1;i<I;++i) #define fd(i,a,b) for(R int i=(a),I=(b)-1;i>I;--i) #define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v) template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;} template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,1:0;} using namespace std; const int P=924844033,gi=554906420; inline void upd(R int &x,R int y){(x+=y)>=P?x-=P:0;} inline int add(R int x,R int y){return x+y>=P?x+y-P:x+y;} inline int dec(R int x,R int y){return x-y<0?x-y+P:x-y;} inline int mul(R int x,R int y){return 1ll*x*y-1ll*x*y/P*P;} int ksm(R int x,R int y){ R int res=1; for(;y;y>>=1,x=mul(x,x))(y&1)?res=mul(res,x):0; return res; } const int N=(1<<19)+5; struct eg{int v,nx;}e[N<<1];int head[N],tot; inline void Add(R int u,R int v){e[++tot]={v,head[u]},head[u]=tot;} int fac[N],ifac[N],r[25][N],rt[2][N],f[N],g[N],inv[25]; int n,lim,d; inline void swap(R int &x,R int &y){R int t=x;x=y,y=t;} inline int C(R int n,R int m){return m>n?0:1ll*fac[n]*ifac[m]%P*ifac[n-m]%P;} void init(){ fac[0]=ifac[0]=1;fp(i,1,262144)fac[i]=mul(fac[i-1],i); ifac[262144]=ksm(fac[262144],P-2);fd(i,262143,1)ifac[i]=mul(ifac[i+1],i+1); fp(d,1,19){ fp(i,1,(1<<d)-1)r[d][i]=(r[d][i>>1]>>1)|((i&1)<<(d-1)); inv[d]=ksm(1<<d,P-2); } for(R int t=(P-1)>>1,i=1,x,y;i<=262144;i<<=1,t>>=1){ x=ksm(5,t),y=ksm(gi,t),rt[0][i]=rt[1][i]=1; fp(k,1,i-1) rt[1][i+k]=mul(rt[1][i+k-1],x), rt[0][i+k]=mul(rt[0][i+k-1],y); } } void NTT(int *A,int ty){ fp(i,0,lim-1)if(i<r[d][i])swap(A[i],A[r[d][i]]); R int t; for(R int mid=1;mid<lim;mid<<=1) for(R int j=0;j<lim;j+=(mid<<1)) fp(k,0,mid-1) A[j+k+mid]=dec(A[j+k],t=mul(rt[ty][mid+k],A[j+k+mid])), A[j+k]=add(A[j+k],t); if(!ty){ t=inv[d]; fp(i,0,lim-1)A[i]=mul(A[i],t); } } int sz[N]; void dfs(int u,int fa){ sz[u]=1; go(u)if(v!=fa){ dfs(v,u),sz[u]+=sz[v]; ++f[n-sz[v]],++f[sz[v]]; } } int main(){ // freopen("testdata.in","r",stdin); scanf("%d",&n); for(R int i=1,u,v;i<n;++i)scanf("%d%d",&u,&v),Add(u,v),Add(v,u); dfs(1,0);init(); lim=1,d=0; while(lim<=(n<<1))lim<<=1,++d; fp(i,0,n)f[i]=mul(f[i],fac[i]),g[i]=ifac[n-i]; NTT(f,1),NTT(g,1); fp(i,0,lim-1)f[i]=mul(f[i],g[i]); NTT(f,0); fp(i,1,n)printf("%d\n",dec(mul(n,C(n,i)),mul(f[i+n],ifac[i]))); return 0; }
来源:https://www.cnblogs.com/yuanquming/p/11361628.html