省选模拟9

A. 体育测试

将限制分为两类

\(f_{i,j}\) 表示前 \(i\) 个位置选了 \(j\) 个二类点的方案数

\(dp\) 时只考虑二类点,在有一类点结束时再乘上贡献的系数

边界 \(f_{0,0}=1\)

设目前有 \(t\) 个二类点开始了,没有结束的一类点还有 \(k\)

转移 \(f_{i,j}=f_{i-1,j-1}*(t-j+1)+f_{i-1,j}\)

如果当前点有 \(x\) 个一类点结束那么就要乘上 \(\binom{k}{x}*x!\) 种选择一类点的方案数

Code
#include<bits/stdc++.h>
#define int long long
#define rint signed
#define mod 1000000007
#define debug(args...) fprintf(stderr,args);
#define inf 0x3f3f3f3f3f3f3f3f
using namespace std;
inline int read(){
	int x=0,f=1;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
	return x*f;
}
int n;
int a[5010],num[5010];
int p1[5010],p2[5010];
int f[5010][5010];
int fac[5010],inv[5010];
inline int C(int n,int m){return fac[n]*inv[m]%mod*inv[n-m]%mod;}
inline int qpow(int x,int k){
	int res=1,base=x;
	while(k){if(k&1) res=res*base%mod;base=base*base%mod;k>>=1;}
	return res;
}
signed main(){
#ifdef LOCAL
	freopen("in","r",stdin);
	freopen("out","w",stdout);
#endif
	freopen("test.in","r",stdin);
	freopen("test.out","w",stdout);
	inv[0]=fac[0]=1;for(int i=1;i<=5000;i++) fac[i]=fac[i-1]*i%mod,inv[i]=inv[i-1]*qpow(i,mod-2)%mod;
	n=read();
	for(int i=1;i<=n;i++){a[i]=read();if(a[i]>0) p1[a[i]]++;else p2[-a[i]]++;}
	for(int i=1;i<=n;i++) p2[i]+=p2[i-1],p1[i]+=p1[i-1];f[0][0]=1;
	for(int i=1,k;i<=n;i++) for(int j=0;j<=p2[i]&&j<=i;j++){
		f[i][j]+=f[i-1][j];
		if(j) f[i][j]+=f[i-1][j-1]*(p2[i]-j+1);
		k=i-j-p1[i-1];
		f[i][j]%=mod;
		if(k>=p1[i]-p1[i-1]) f[i][j]=f[i][j]*C(k,p1[i]-p1[i-1])%mod*fac[p1[i]-p1[i-1]]%mod;
		else f[i][j]=0;
	}
	printf("%lld\n",f[n][p2[n]]);
	return 0;
}

B. 贸易

多项式模板题,先背个板写个点分治 \(+\) \(ntt\) 求出每种路径长度的个数设为 \(dis_i\)

然后答案就是 \(\frac{b\sum\limits_{i=0}^ndis_i(1-p_i)^i}{n^2}-a\)

再写个多项式多点求值就行了

Code
#include<bits/stdc++.h>
#define int long long
#define rint signed
#define LLL(args...) fprintf(stderr,args)
#define mod 998244353
#define inf 0x3f3f3f3f3f3f3f3f
using namespace std;
inline int read(){
	int x=0,f=1;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
	return x*f;
}
int n,m,rt,S,mxd,inv;
int head[100010],ver[200010],to[200010],tot;
int siz[100010],mx[100010];
int dis[262150],val[100010];
bool vis[100010];
struct QUE{int a,b,x;}LL[100010];
vector<int>a,F,A,ANS;
inline void md(int &x){x=(x>=mod)?x-mod:x;}
inline void add(int x,int y){ver[++tot]=y;to[tot]=head[x];head[x]=tot;}
inline int qpow(int x,int k){
	int res=1,base=x;
	while(k){if(k&1) res=res*base%mod;base=base*base%mod;k>>=1;}
	return res;
}
namespace POLY{
	int inv;
	vector<int> r,g,T,Q[400010];
	inline void init(int len,int L){
		for(int i=0;i<len;i++) r[i]=(r[i>>1]>>1)|((i&1)<<(L-1));
		g[0]=1,g[1]=qpow(3,(mod-1)/len);for(int i=2;i<len;i++) g[i]=g[i-1]*g[1]%mod;
	}
	inline void rev(int len){g[0]=1,g[1]=qpow(g[1],mod-2);for(int i=2;i<len;i++) g[i]=g[i-1]*g[1]%mod;}
	inline void ntt(vector<int> &a,int len){
		for(int i=0;i<len;i++) if(i<r[i]) swap(a[i],a[r[i]]);
		for(int d=1,t=len>>1;d<len;d<<=1,t>>=1) for(int i=0;i<len;i+=(d<<1)) for(int j=0;j<d;j++){
			int tmp=g[t*j]*a[i+j+d]%mod;
			md(a[i+j+d]=a[i+j]-tmp+mod);
			md(a[i+j]=a[i+j]+tmp);
		}
	}
	inline vector<int> Mul(vector<int> F,vector<int> G){
		int len,L,siz;
		siz=F.size()+G.size()-1;
		for(len=1,L=0;len<siz;len<<=1,L++);init(len,L);
		F.resize(len);G.resize(len);
		ntt(F,len);ntt(G,len);rev(len);
		for(int i=0;i<len;i++) F[i]=F[i]*G[i]%mod;
		ntt(F,len);inv=qpow(len,mod-2);
		for(int i=0;i<len;i++) F[i]=F[i]*inv%mod;
		return F;
	}
	inline vector<int> Mult(vector<int> F,vector<int> G){
		int n=F.size(),m=G.size();
		reverse(G.begin(),G.end());G=Mul(F,G);
		for(int i=0;i<n;i++) F[i]=G[i+m-1];
		return F;
	}
	inline vector<int> INV(vector<int> F,int n){
		vector<int>G;G.resize(1);
		G[0]=qpow(F[0],mod-2);int len,L;
		for(L=1,len=2;(len>>1)<n;){
			for(int i=0;i<len;i++) T[i]=F[i];
			len<<=1,L++;init(len,L);
			for(int i=len>>1;i<len;i++) T[i]=0;G.resize(len);
			ntt(G,len);ntt(T,len);rev(len);
			for(int i=0;i<len;i++) G[i]=(2ll-T[i]*G[i]%mod+mod)%mod*G[i]%mod;
			ntt(G,len);inv=qpow(len,mod-2);
			for(int i=len>>1;i<len;i++) G[i]=0;
			for(int i=0,lim=len>>1;i<lim;i++) G[i]=G[i]*inv%mod;
		}
		for(int i=n;i<len;i++) G[i]=0;
		return G;
	}
	#define lson rt<<1
	#define rson rt<<1|1
	void init(vector<int> &a,int rt,int l,int r){
		if(l==r){Q[rt].resize(2);Q[rt][0]=1,Q[rt][1]=mod-a[l];return ;}
		int mid=(l+r)>>1;
		init(a,lson,l,mid);init(a,rson,mid+1,r);
		Q[rt]=Mul(Q[lson],Q[rson]);
	}
	void multi(int rt,int l,int r,vector<int> f,vector<int> &g){
		f.resize(r-l+1);
		if(l==r) return g[l]=f[0],void();
		int mid=(l+r)>>1;
		multi(lson,l,mid,Mult(f,Q[rson]),g);
		multi(rson,mid+1,r,Mult(f,Q[lson]),g);
	}
	void multipoint(vector<int> f,vector<int> a,vector<int> &ans,int n){
		f.resize(n+1);a.resize(n);
		init(a,1,0,n-1);ans.resize(n);
		multi(1,0,n-1,Mult(f,INV(Q[1],n+1)),ans);
	}
	inline void INIT(){T.resize(524290);r.resize(524290);g.resize(524290);}
	#undef lson
	#undef rson
}
void getrt(int x,int fa){
	siz[x]=1;mx[x]=0;
	for(int i=head[x];i;i=to[i]){
		int y=ver[i];
		if(y==fa||vis[y]) continue;
		getrt(y,x);
		siz[x]+=siz[y];
		mx[x]=max(mx[x],siz[y]);
	}
	mx[x]=max(mx[x],S-siz[x]);
	if(mx[x]<mx[rt]) rt=x;
}
void dfs(int x,int fa,int dep){
	a[dep]++;mxd=max(mxd,dep);
	for(int i=head[x];i;i=to[i]){
		int y=ver[i];
		if(y==fa||vis[y]) continue;
		dfs(y,x,dep+1);
	}
}
void calc(int x,int dep,int opt){
	mxd=0;dfs(x,0,dep);
	int len=1,L=0;
	for(;len<=mxd+mxd;len<<=1,L++);POLY::init(len,L);
	POLY::ntt(a,len);POLY::rev(len);
	for(int i=0;i<len;i++) a[i]=a[i]*a[i]%mod;
	POLY::ntt(a,len);POLY::inv=qpow(len,mod-2);
	for(int i=0;i<len;i++) a[i]=a[i]*POLY::inv%mod;
	for(int i=0;i<len;i++) dis[i]+=opt*a[i],a[i]=0;
}
void solve(int x){
	vis[x]=1;calc(x,0,1);
	for(int i=head[x];i;i=to[i]){
		int y=ver[i];
		if(vis[y]) continue;
		calc(y,1,-1);
		S=siz[y];mx[rt=0]=inf;
		getrt(y,0);solve(rt);
	}
}
inline void pre(){
	F.resize(n+1);A.resize(m);
	for(int i=0;i<=n;i++) F[i]=dis[i];
	for(int i=0;i<m;i++) A[i]=LL[i+1].x;
}
inline int calc(int x){
	int res=0;
	for(int i=0,base=1;i<=n;i++,base=base*x%mod){
		if(!dis[i]) break;
		md(res=(res+base*dis[i]%mod));
	}
	return res;
}
signed main(){
#ifdef LOCAL
	freopen("in","r",stdin);
	freopen("out","w",stdout);
#endif
	freopen("trade.in","r",stdin);
	freopen("trade.out","w",stdout);
	n=read(),m=read();a.resize(524290);POLY::INIT();
	for(int i=1,x,y;i<n;i++){
		x=read(),y=read();
		add(x,y),add(y,x);
	}
	S=n;mx[rt=0]=inf;
	getrt(1,0);solve(rt);
	for(int i=1,x,y;i<=m;i++){
		LL[i].a=read(),LL[i].b=read();
		x=read(),y=read();LL[i].x=(1-x*qpow(y,mod-2)%mod+mod)%mod;
	}
	pre();POLY::multipoint(F,A,ANS,max(n+1,m));
	for(int i=0,res;i<m;i++){
		res=LL[i+1].b*ANS[i]%mod*qpow(n*n%mod,mod-2)%mod;
		md(res=(res-LL[i+1].a+mod));
		printf("%lld\n",res);
	}
	return 0;
}

C. 密码

用相同的随机数种子随出一个 \(m\)\(n\) 列的矩阵

然后让编码输出的串表示这一位表示的那一行参不参与 \(xor\) 运算

用线性基把 \(?\) 的位置都差入,再考虑把要编码的串的位置都变成 \(1\) 或者 \(0\)

然后得出每个位置是否需要参与运算

然后解码解出来的就是把那些行都 \(xor\) 起来

Code
#include "password.h"
#include<bits/stdc++.h>
#define debug(args...) fprintf(stderr,args)
using namespace std;
inline int read(){
	int x=0,f=1;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
	return x*f;
}
int N,t[2100];
bool res[2100];
bitset<2100>B[2100],T[2100],TT[2100],now;
inline void ins(int id){
	TT[id][id]=1;
	for(int i=1;i<=N;i++) if(B[id][i]==1){
		if(t[i]) B[id]^=T[i],TT[id]^=TT[t[i]];
		else{t[i]=id;T[i]=B[id];break;}
	}
}
void encoder(int n,int m,int k,const char* a,const char* b,char* ans){
	mt19937 rd(998244353);
	N=n;
	for(int j=1;j<=m;j++) for(int i=1;i<=n;i++) B[j][i]=rd()%2;
	for(int i=1;i<=n;i++) if(a[i-1]=='1') now[i]=1;
	for(int i=1;i<=m;i++) if(b[i-1]=='1') now^=B[i];else if(b[i-1]=='?') ins(i);
	for(int i=1;i<=n;i++) if(now[i]==0){now^=T[i];for(int j=1;j<=m;j++) res[j]^=TT[t[i]][j];}
	for(int i=1;i<=m;i++) if(b[i-1]=='?') ans[i-1]=res[i]+'0';else ans[i-1]=b[i-1];
}
void decoder(int n,int m,const char* a,char* ans){
	mt19937 rd(998244353);now.reset();
	for(int i=1;i<=n;i++) now[i]=1;
	for(int j=1;j<=m;j++) for(int i=1;i<=n;i++) B[j][i]=rd()%2;
	for(int i=1;i<=m;i++) if(a[i-1]=='1') now^=B[i];
	for(int i=1;i<=n;i++) ans[i-1]=now[i]+'0';
}

然而有更巧妙的通过方法

本来以为会初始化,然后我就给他把答案串输出到了一个文件里,然后再读入,亲测有效

结果发现并没有初始化,于是直接开个数组存下来就行

Code
#include "password.h"
#include<bits/stdc++.h>
#define debug(args...) fprintf(stderr,args)
using namespace std;
void encoder(int n,int m,int k,const char* a,const char* b,char* ans){
	freopen("ans.tmp","w",stderr);
	for(int i=0;i<m;i++) if(b[i]=='?') ans[i]='0';else ans[i]=b[i];
	debug("%s\n",a);
	fclose(stderr);
}
void decoder(int n,int m,const char* a,char* ans){
	freopen("ans.tmp","r",stdin);
	scanf("%s",ans);
	fclose(stdin);
}
Code
#include "password.h"
char str[1010];
void encoder(int n,int m,int k,const char* a,const char* b,char* ans){for(int i=0;i<m;i++) if(b[i]=='?') ans[i]='0';else ans[i]=b[i];for(int i=0;i<n;i++) str[i]=a[i];}
void decoder(int n,int m,const char* a,char* ans){for(int i=0;i<n;i++) ans[i]=str[i];}
posted @ 2022-01-25 20:35  Max_QAQ  阅读(65)  评论(0编辑  收藏  举报