【2020省选模拟】题解

T1:

k t h min ⁡ − max ⁡ kth \min-\max kthminmax容斥后
一个集合期望为 ( n + 1 2 ) w , w \frac{{n+1\choose 2}}{w},w w(2n+1),w是相交区间数
于是暴力 O ( n 5 ) d p O(n^5)dp O(n5)dp可过

f s y fsy fsy有神仙的四方做法但是我不会/kk

#include<bits/stdc++.h>
using namespace std;
#define cs const
#define pb push_back
#define pii pair<int,int>
#define fi first
#define se second
#define ll long long
#define bg begin
namespace IO{
	cs int RLEN=1<<20|1;
	char ibuf[RLEN],*ib,*ob;
	inline char gc(){
		(ib==ob)&&(ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
		return (ib==ob)?EOF:*ib++;
	}
	inline int read(){
		char ch=gc();
		int res=0;bool f=0;
		while(!isdigit(ch))f=(ch=='-'),ch=gc();
		while(isdigit(ch))res=(res*10)+(ch^48),ch=gc();
		return f?-res:res;
	}
}using IO::read;
template<typename tp>inline void chemx(tp &a,tp b){return (a<b)?(a=b):0;}
template<typename tp>inline void chemn(tp &a,tp b){return (a>b)?(a=b):0;}
cs int mod=998244353;
inline int add(int a,int b){return a+b>=mod?a+b-mod:a+b;}
inline int dec(int a,int b){return a<b?a-b+mod:a-b;}
inline int mul(int a,int b){static ll r;r=(ll)a*b;return (r>=mod)?(r%mod):r;}
inline void Add(int &a,int b){a=a+b>=mod?a+b-mod:a+b;}
inline void Dec(int &a,int b){a=a<b?a-b+mod:a-b;}
inline void Mul(int &a,int b){static ll r;r=(ll)a*b;a=(r>=mod)?(r%mod):r;}
inline int ksm(int a,int b,int res=1){for(;b;b>>=1,Mul(a,a))(b&1)&&(Mul(res,a),1);return res;}
inline int Inv(int x){return ksm(x,mod-2);}
cs int N=105;
char xx;
int c[N][N],f[N][N][N*N/2],n,m,iv[N*N],S[N];
char yy;
int main(){
	n=read(),m=n-read()+1;
	for(int i=0;i<N;i++){
		c[i][i]=c[i][0]=1;
		for(int j=1;j<i;j++)c[i][j]=add(c[i-1][j],c[i-1][j-1]);
	}iv[0]=iv[1]=1;
	for(int i=2;i<N*N;i++)iv[i]=mul(mod-mod/i,iv[mod%i]);
	for(int i=0;i<N;i++)S[i]=(i*(i+1))>>1;
	f[0][0][0]=1;
	int sm=S[n],res=0;
	for(int i=0;i<=n;i++)
	for(int j=0;j<=i;j++)
	for(int k=0,l=S[i];k<=l;k++)if(f[i][j][k]){
		int vl=f[i][j][k];
		int now=mul(vl,mul(c[j-1][m-1],mul(sm,iv[sm-k-S[n-i]])));
//		cout<<now<<" "<<i<<" "<<j<<" "<<k<<'\n';
		if((j+m)&1)Dec(res,now);else Add(res,now);
		for(int p=i+1;p<=n;p++){
			Add(f[p][j+1][k+S[p-i-1]],vl);
		}
	}cout<<res<<'\n';
}

T2:

考虑 f [ u ] f[u] f[u]表示 u u u内全部分配好的方案数
那么对于经过 u u u的路径方案是路径所有点其余儿子的积
合法即 s u + s v − s l c a − s f a l c a ≥ 0 s_u+s_v-s_{lca}-s_{fa_{lca}}\geq0 su+svslcasfalca0
于是可以在 l c a lca lca线段树维护答案
继承重儿子的线段树再一个个暴力加轻儿子子树所有点
积可以每个点记一下前后缀

复杂度 O ( n l o g 2 n ) O(nlog^2n) O(nlog2n)
不知道为什么永远跑不过仲爺

#include<bits/stdc++.h>
using namespace std;
#define cs const
#define re register
#define pb push_back
#define pii pair<int,int>
#define ll long long
#define y1 shinkle
#define fi first
#define se second
#define bg begin
cs int RLEN=1<<20|1;
inline char gc(){
    static char ibuf[RLEN],*ib,*ob;
    (ib==ob)&&(ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
    return (ib==ob)?EOF:*ib++;
}
#define gc getchar
inline int read(){
    char ch=gc();
    int res=0;bool f=1;
    while(!isdigit(ch))f^=ch=='-',ch=gc();
    while(isdigit(ch))res=(res*10)+(ch^48),ch=gc();
    return f?res:-res;
}
inline ll readll(){
    char ch=gc();
    ll res=0;bool f=1;
    while(!isdigit(ch))f^=ch=='-',ch=gc();
    while(isdigit(ch))res=(res*10)+(ch^48),ch=gc();
    return f?res:-res;
}
inline char readchar(){
	char ch=gc();
	while(isspace(ch))ch=gc();
	return ch;
}
inline int readstring(char *s){
	int top=0;char ch=gc();
	while(isspace(ch))ch=gc();
	while(!isspace(ch)&&ch!=EOF)s[++top]=ch,ch=gc();
	s[top+1]='\0';return top;
}
template<typename tp>inline void chemx(tp &a,tp b){a=max(a,b);}
template<typename tp>inline void chemn(tp &a,tp b){a=min(a,b);}
cs int mod=1e9+7;
inline int add(int a,int b){return (a+b)>=mod?(a+b-mod):(a+b);}
inline int dec(int a,int b){return (a<b)?(a-b+mod):(a-b);}
inline int mul(int a,int b){static ll r;r=(ll)a*b;return (r>=mod)?(r%mod):r;}
inline void Add(int &a,int b){a=(a+b)>=mod?(a+b-mod):(a+b);}
inline void Dec(int &a,int b){a=(a<b)?(a-b+mod):(a-b);}
inline void Mul(int &a,int b){static ll r;r=(ll)a*b;a=(r>=mod)?(r%mod):r;}
inline int ksm(int a,int b,int res=1){for(;b;b>>=1,Mul(a,a))(b&1)&&(Mul(res,a),1);return res;}
inline int Inv(int x){return ksm(x,mod-2);}
inline int fix(ll x){x%=mod;return (x<0)?x+mod:x;}
cs int N=1e5+5,INF=1e9;
int rt;
namespace Seg{
	cs int N=::N*100;
	int lc[N],rc[N],s[N],tag[N],tot;
	inline int newnode(){
		int u=++tot;tag[u]=1,lc[u]=rc[u]=s[u]=0;
		return u;
	}
	inline void clear(){tot=rt=0;}
	inline void pushnow(int u,int k){Mul(tag[u],k),Mul(s[u],k);}
	inline void pushdown(int u){
		if(tag[u]==1)return;
		if(lc[u])pushnow(lc[u],tag[u]);
		if(rc[u])pushnow(rc[u],tag[u]);
		tag[u]=1;
	}
	#define mid ((l+r)>>1)
	void ins(int &u,int l,int r,int p,int k){
		if(!u)u=newnode();
		pushdown(u);
		Add(s[u],k);if(l==r)return;
		(p<=mid)?ins(lc[u],l,mid,p,k):ins(rc[u],mid+1,r,p,k);
	}
	int qry(int u,int l,int r,int p){
		if(!u||p<=l)return s[u];
		pushdown(u);
		if(p<=mid)return add(qry(lc[u],l,mid,p),s[rc[u]]);
		return qry(rc[u],mid+1,r,p);
	}
	inline int query(int p){return qry(rt,-INF,INF,p);}
	inline void insert(int p,int k){return ins(rt,-INF,INF,p,k);}
	inline void update(int k){return pushnow(rt,k);}
	#undef mid
}
using Seg::query;
using Seg::insert;
using Seg::update;
using Seg::clear;
vector<int> e[N];
int vl[N],n,siz[N],f[N],fa[N];
int l[N],r[N],son[N*3],pre[N*3],suf[N*3],dfn;
void dfs1(int u){
	siz[u]=1;vl[u]+=vl[fa[u]];
	for(int v:e[u])if(v!=fa[u]){
		fa[v]=u,dfs1(v),siz[u]+=siz[v];
	}
	l[u]=r[u]=dfn+1;
	for(int v:e[u])if(v!=fa[u]){
		son[++r[u]]=v;
	}r[u]++;dfn=r[u];
	sort(son+l[u]+1,son+r[u],[](cs int &i,cs int &j){return siz[i]>siz[j];});
}
int tot;
pii p[N];
void collect(int u,int sm){
	p[++tot]=pii(vl[u],mul(sm,pre[r[u]-1]));
	for(int i=l[u];i<r[u];i++)
	collect(son[i],mul(sm,mul(pre[i-1],suf[i+1])));
}
void dfs2(int u){
//	cout<<"int "<<u<<'\n';
	for(int i=l[u]+2;i<=r[u];i++)dfs2(son[i]),clear();
	if(l[u]+1<r[u])dfs2(son[l[u]+1]);
	pre[l[u]]=suf[r[u]]=1;
	for(int i=l[u]+1;i<r[u];i++)pre[i]=mul(pre[i-1],f[son[i]]);
	for(int i=r[u]-1;i>l[u];i--)suf[i]=mul(suf[i+1],f[son[i]]);
	if(vl[u]-vl[fa[u]]>=0)Add(f[u],pre[r[u]-1]);
	Add(f[u],mul(suf[l[u]+2],query(vl[fa[u]])));
//		cout<<u<<" "<<vl[u]-vl[fa[u]]<<" "<<f[u]<<" "<<l[u]<<" "<<r[u]<<" "<<'\n';
	for(int i=l[u]+2;i<r[u];i++){
		tot=0;collect(son[i],1);
		for(int j=1;j<=tot;j++){
			if(p[j].fi>=vl[fa[u]])Add(f[u],mul(p[j].se,mul(pre[i-1],suf[i+1])));
			Add(f[u],mul(suf[i+1],mul(p[j].se,query(vl[u]+vl[fa[u]]-p[j].fi))));
		}
		update(f[son[i]]);
		for(int j=1;j<=tot;j++)insert(p[j].fi,mul(p[j].se,pre[i-1]));
	}
	insert(vl[u],pre[r[u]-1]);
}
int main(){
	#ifdef Stargazer
	freopen("lx.in","r",stdin);
	#endif
	int size=40<<20;//40M
    //__asm__ ("movl  %0, %%esp\n"::"r"((char*)malloc(size)+size));//调试用这个 
    __asm__ ("movq %0,%%rsp\n"::"r"((char*)malloc(size)+size));//提交用这个 
	n=read();
	for(int i=1;i<=n;i++)vl[i]=read();
	for(int i=1;i<n;i++){
		int u=read(),v=read();
		e[u].pb(v),e[v].pb(u);
	}dfs1(1);
	dfs2(1);
	cout<<f[1];exit(0);//必须用exit 
	return 0;
}

T3:

考虑把平面树除去根转对偶
就变成圆上 2 n 2n 2n个点匹配,路径不交,旋转同构

显然 b u r n s i d e burnside burnside
不旋转即为卡特兰数 ( 2 n n ) − ( 2 n n − 1 ) {2n\choose n}-{2n\choose n-1} (n2n)(n12n)
对于奇数 n − 1 2 \frac{n-1}{2} 2n1为特殊的中心对称,单独算
否则枚举循环节大小 d d d,那么 2 d 2d 2d中任意 d d d个做左括号有唯一合法方案

然后就做完了

#include<bits/stdc++.h>
using namespace std;
#define cs const
#define re register
#define pb push_back
#define pii pair<int,int>
#define ll long long
#define y1 shinkle
#define fi first
#define se second
#define bg begin

namespace IO{

cs int RLEN=1<<20|1;
char ibuf[RLEN],*ib,*ob;
inline char gc(){
    (ib==ob)&&(ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
    return (ib==ob)?EOF:*ib++;
}
inline int read(){
    char ch=gc();
    int res=0;bool f=1;
    while(!isdigit(ch))f^=ch=='-',ch=gc();
    while(isdigit(ch))res=(res*10)+(ch^48),ch=gc();
    return f?res:-res;
}
inline ll readll(){
    char ch=gc();
    ll res=0;bool f=1;
    while(!isdigit(ch))f^=ch=='-',ch=gc();
    while(isdigit(ch))res=(res*10)+(ch^48),ch=gc();
    return f?res:-res;
}
inline char readchar(){
	char ch=gc();
	while(isspace(ch))ch=gc();
	return ch;
}
inline int readstring(char *s){
	int top=0;char ch=gc();
	while(isspace(ch))ch=gc();
	while(!isspace(ch)&&ch!=EOF)s[++top]=ch,ch=gc();
	s[top+1]='\0';return top;
}

}
using IO::read;
template<typename tp>inline void chemx(tp &a,tp b){a=max(a,b);}
template<typename tp>inline void chemn(tp &a,tp b){a=min(a,b);}
int mod;
inline int add(int a,int b){return (a+b)>=mod?(a+b-mod):(a+b);}
inline int dec(int a,int b){return (a<b)?(a-b+mod):(a-b);}
inline int mul(int a,int b){static ll r;r=(ll)a*b;return (r>=mod)?(r%mod):r;}
inline void Add(int &a,int b){a=(a+b)>=mod?(a+b-mod):(a+b);}
inline void Dec(int &a,int b){a=(a<b)?(a-b+mod):(a-b);}
inline void Mul(int &a,int b){static ll r;r=(ll)a*b;a=(r>=mod)?(r%mod):r;}
inline int ksm(int a,int b,int res=1){for(;b;b>>=1,Mul(a,a))(b&1)&&(Mul(res,a),1);return res;}
inline int Inv(int x){return ksm(x,mod-2);}
inline int fix(ll x){x%=mod;return (x<0)?x+mod:x;}
cs int N=1e5+5;
int fac[N],ifac[N],phi[N],pr[N],tot;
bool vis[N];
inline void init(cs int n=N-5){
	phi[1]=1;
	for(int i=2;i<=n;i++){
		if(!vis[i])pr[++tot]=i,phi[i]=i-1;
		for(int j=1;j<=tot&&i*pr[j]<=n;j++){
			vis[i*pr[j]]=1;
			if(i%pr[j]==0){
				phi[i*pr[j]]=phi[i]*pr[j];break;
			}
			phi[i*pr[j]]=phi[i]*(pr[j]-1);
		}
	}
}
int n;
inline void init_fac(){
	fac[0]=ifac[0]=1;
	for(int i=1;i<N;i++)fac[i]=mul(fac[i-1],i);
	ifac[N-1]=Inv(fac[N-1]);
	for(int i=N-2;i;i--)ifac[i]=mul(ifac[i+1],i+1);
}
inline int C(int n,int m){return (n<m||n<0||m<0)?0:mul(fac[n],mul(ifac[m],ifac[n-m]));}
inline int Cat(int n){return dec(C(2*n,n),C(2*n,n-1));}
inline void solve(){
	n=read()-1,mod=read();
	init_fac();
	int res=Cat(n);
	if(n&1)Add(res,C(n,n/2));
	for(int i=1;i<n;i++)if(n%i==0)Add(res,mul(C(2*i,i),phi[n/i]));
	Mul(res,Inv(2*n));cout<<res<<'\n';return;
}
int main(){
	#ifdef Stargazer
	freopen("lx.in","r",stdin);
	#endif
	init();
	int T=read();
	while(T--)solve();
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值