【2020省选模拟】题解

T1

考虑记出欧拉回路图后任意断/连边都可行
D P DP DP只需要考虑简单容斥一下即可

#include<bits/stdc++.h>
using namespace std;
#define cs const
#define pb push_back
#define ll long long 
#define pii pair<int,int>
#define fi first
#define se second
#define bg begin
cs int RLEN=(1<<20)|3;
inline char gc(){
	static char ibuf[RLEN],*ib,*ob;
	(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 int readstring(char *s){
	char ch=gc();int l=0;
	while(isspace(ch))ch=gc();
	while(!isspace(ch)&&ch!=EOF)s[++l]=ch,ch=gc();
	return l;
}
inline char readchar(){
	char ch=gc();
	while(isspace(ch))ch=gc();return ch;
}
template<typename tp>inline void chemx(tp &a,tp b){a<b?a=b:0;}
template<typename tp>inline void chemn(tp &a,tp b){a<b?a=b:0;}
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);}
cs int N=2005;
int fac[N],ifac[N],f[N],g[N],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]));}
int main(){
	#ifdef Stargazer
	freopen("lx.in","r",stdin);
	#endif
	init_fac(),n=read();
	g[1]=f[1]=1;
	for(int i=2;i<=n;i++)f[i]=g[i]=ksm(2,(ll)(i-1)*(i-2)/2);
	for(int i=2;i<=n;i++)
	for(int j=1;j<i;j++)Dec(f[i],mul(C(i-1,j-1),mul(f[j],g[i-j])));
	cout<<mul(n*(n-1)>>1,f[n])<<'\n';return 0;
}

T2

以每个格子左上角跑出的最短路树一定不会被走的路径断开
然后每个格子拆成四个角四个点表位置然后跑 d i j dij dij即可

#include<bits/stdc++.h>
using namespace std;
#define cs const
#define pb push_back
#define ll long long 
#define pii pair<int,int>
#define fi first
#define se second
#define bg begin
cs int RLEN=(1<<20)|3;
inline char gc(){
	static char ibuf[RLEN],*ib,*ob;
	(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 int readstring(char *s){
	char ch=gc();int l=0;
	while(isspace(ch))ch=gc();
	while(!isspace(ch)&&ch!=EOF)s[++l]=ch,ch=gc();
	return l;
}
inline char readchar(){
	char ch=gc();
	while(isspace(ch))ch=gc();return ch;
}
template<typename tp>inline void chemx(tp &a,tp b){a<b?a=b:0;}
template<typename tp>inline void chemn(tp &a,tp b){a<b?a=b:0;}
cs int dx[4]={-1,1,0,0},dy[4]={0,0,-1,1};
cs int N=405,M=N*N*4*2;
int adj[M],nxt[M<<1],to[M<<1],val[M<<1],ecnt;
inline void addedge(int u,int v,int w){
	if(!u||!v)return;
	nxt[++ecnt]=adj[u],adj[u]=ecnt,to[ecnt]=v,val[ecnt]=w;
	nxt[++ecnt]=adj[v],adj[v]=ecnt,to[ecnt]=u,val[ecnt]=w;
}
bool vis[N][N],ok[N][N][4],t[N][N],vt[N*N*4];
int n,m,ln[N][N],rw[N][N],pre[N][N],id[N][N][4],tot;
ll d[N][N],dis[N*N*4];
inline int ID(int x,int y){return x*(m+2)+y;}
typedef pair<ll,int> pl;
priority_queue<pl,vector<pl>,greater<pl> > q;
inline int VAL(int x,int y,int d){
	switch(d){
		case 0:return ln[x-1][y];
		case 1:return ln[x][y];
		case 2:return rw[x][y-1];
		case 3:return rw[x][y];
	}
}
int main(){
	#ifdef Stargazer
	freopen("lx.in","r",stdin);
	#endif
	n=read(),m=read();
	for(int i=1;i<=n;i++)
	for(int j=1;j<=m;j++)t[i][j]=read();
	for(int i=1;i<=n;i++)
	for(int j=1;j<=m+1;j++)ln[i][j]=read();
	for(int i=1;i<=n+1;i++)
	for(int j=1;j<=m;j++)rw[i][j]=read();
	for(int i=1;i<=n+1;i++)
	for(int j=1;j<=m+1;j++)
	for(int k=0;k<4;k++)
	id[i][j][k]=++tot;
	memset(dis,127/3,sizeof(dis));
	memset(d,127/3,sizeof(d));
	d[1][1]=0;
	q.push(pl(0,ID(1,1)));
	while(q.size()){
		int x=q.top().se/(m+2),y=q.top().se%(m+2);
		q.pop();if(vis[x][y])continue;
		vis[x][y]=1;
		for(int i=0;i<4;i++){
			int px=x+dx[i],py=y+dy[i];
			if(px<1||px>n+1||py<1||py>m+1)continue;
			ll dt=d[x][y]+VAL(x,y,i);
			if(dt<d[px][py]){
				d[px][py]=dt,pre[px][py]=i^1,q.push(pl(dt,ID(px,py)));
			}
		}
	}memset(vis,0,sizeof(vis));
	for(int i=1;i<=n;i++)
	for(int j=1;j<=m;j++)if(t[i][j]){
		int x=i,y=j;
		id[i][j][2]=id[i][j+1][3]=id[i+1][j][1]=id[i+1][j+1][0]=0;
		while(!vis[x][y]&&(x!=1||y!=1)){
			vis[x][y]=1;int d=pre[x][y];
			ok[x][y][d]=1,x+=dx[d],y+=dy[d];
			ok[x][y][d^1]=1;
		}
	}id[1][1][0]=0;
	for(int i=1;i<=n+1;i++)
	for(int j=1;j<=m+1;j++){
		if(!ok[i][j][0])addedge(id[i][j][0],id[i][j][1],0);
		if(!ok[i][j][1])addedge(id[i][j][3],id[i][j][2],0);
		if(!ok[i][j][2])addedge(id[i][j][0],id[i][j][3],0);
		if(!ok[i][j][3])addedge(id[i][j][1],id[i][j][2],0);
	}
	for(int i=1;i<=n+1;i++)
	for(int j=1;j<=m;j++)
	addedge(id[i][j][1],id[i][j+1][0],rw[i][j]),
	addedge(id[i][j][2],id[i][j+1][3],rw[i][j]);
	for(int i=1;i<=n;i++)
	for(int j=1;j<=m+1;j++)
	addedge(id[i][j][2],id[i+1][j][1],ln[i][j]),
	addedge(id[i][j][3],id[i+1][j][0],ln[i][j]);
	dis[id[1][1][1]]=0,q.push(pl(0,id[1][1][1]));
	while(q.size()){
		int u=q.top().se;q.pop();
		if(vt[u])continue;
		vt[u]=1;
		for(int e=adj[u],v;e;e=nxt[e])if(dis[v=to[e]]>dis[u]+val[e]){
			dis[v]=dis[u]+val[e];
			q.push(pl(dis[v],v));
		}
	}cout<<dis[id[1][1][3]]<<'\n';
	return 0;
}

T3

考虑看做 n n n个颜色球,每个有 a i a_i ai个,有编号
每个颜色必须编号 1 1 1在最前面
这样方案数就是 m ! ∏ s \frac{m!}{\prod s} sm!

现在相当于不考虑第一个出现的球的限制
枚举每一个然后容斥,枚举后面有几个 1 1 1,直接 D P DP DP即可

似乎按照 l d x ldx ldx的教育,用多项式实现可以做到两个 l o g log log?
分治ntt是两个,平衡结合似乎可以一个log

#include<bits/stdc++.h>
using namespace std;
#define cs const
#define pb push_back
#define ll long long 
#define pii pair<int,int>
#define fi first
#define se second
#define bg begin
cs int RLEN=(1<<20)|3;
inline char gc(){
	static char ibuf[RLEN],*ib,*ob;
	(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 int readstring(char *s){
	char ch=gc();int l=0;
	while(isspace(ch))ch=gc();
	while(!isspace(ch)&&ch!=EOF)s[++l]=ch,ch=gc();
	return l;
}
inline char readchar(){
	char ch=gc();
	while(isspace(ch))ch=gc();return ch;
}
template<typename tp>inline void chemx(tp &a,tp b){a<b?a=b:0;}
template<typename tp>inline void chemn(tp &a,tp b){a<b?a=b:0;}
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);}
cs int N=1005,M=55;
int fac[N],ifac[N],iv[N];
inline void init_C(){
	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);
	iv[0]=iv[1]=1;
	for(int i=2;i<N;i++)iv[i]=mul(mod-mod/i,iv[mod%i]);
}
inline int C(int n,int m){return (n<m||n<0||m<0)?0:mul(fac[n],mul(ifac[m],ifac[n-m]));}
int n,m,a[M];
int f[N];
int main(){
	#ifdef Stargazer
	freopen("lx.in","r",stdin);
	#endif
	init_C();n=read();
	int res=0,pr=1;
	for(int i=1;i<=n;i++)a[i]=read(),m+=a[i],Mul(pr,iv[a[i]]);
	for(int p=1;p<=n;p++){
		int s=0;
		memset(f,0,sizeof(f));
		f[a[p]]=1,s=a[p];
		for(int i=1;i<=n;i++)if(i^p){
			for(int j=s;~j;j--)
			Dec(f[j+a[i]],f[j]);
			s+=a[i];
		}
		int now=0;
		for(int i=a[p];i<=m;i++)
			Add(now,mul(f[i],mul(fac[m],iv[i])));
		Add(res,mul(now,mul(pr,mul(a[p],a[p]))));
	}cout<<res<<'\n';return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值