Examples

2022-7-25 #17 UR12

最近很摆,很久没更博了。😥😥😥

打各种比赛都不知道为什么一直被虐,太奇怪了。

045 uoj#180. 【UR #12】实验室外的攻防战

比较简单的题,感觉之前在 CF 见过?

模拟冒泡排序的过程,用线段树动态维护区间最小值就好了。

写错好多发,真的蚌埠住。。。

#include<stdio.h>
#define lc(x) (x<<1)
#define rc(x) (x<<1|1)
#define mid (l+r>>1)
const int maxn=100005,maxt=maxn<<2;
int n;
int a[maxn],b[maxn],mn[maxt],p[maxn];
inline int min(int a,int b){
	return a<b? a:b;
}
void modify(int l,int r,int now,int p,int v){
	if(l==r){
		mn[now]=v;
		return ;
	}
	if(p<=mid)
		modify(l,mid,lc(now),p,v);
	else modify(mid+1,r,rc(now),p,v);
	mn[now]=min(mn[lc(now)],mn[rc(now)]);
}
int query(int l,int r,int now,int L,int R){
	if(L>R)
		return n+1;
	if(L<=l&&r<=R)
		return mn[now];
	int res=n+1;
	if(L<=mid)
		res=min(res,query(l,mid,lc(now),L,R));
	if(mid<R)
		res=min(res,query(mid+1,r,rc(now),L,R));
	return res;
}
int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
		scanf("%d",&a[i]),p[a[i]]=i,modify(1,n,1,i,a[i]);
	for(int i=1;i<=n;i++){
		scanf("%d",&b[i]);
		int pos=p[b[i]];
		if(query(1,n,1,1,pos-1)<b[i]){
			puts("NO");
			return 0;
		}
		modify(1,n,1,pos,n+1);
	}
	puts("YES");
	return 0;
}

046 uoj#181. 【UR #12】密码锁

也比较简单?

竞赛图强连通分量数量等于割集数量+1。(因为缩点之后是链状的)

不能暴力枚举点集,但是可以发现对于不同特殊边连通块,它们之间的影响是很小的,我们完全可以对于每个连通块枚举点集,最后用背包合并。

复杂度 \(O((n+m)2^m)\)

#include<stdio.h>
#include<vector>
using namespace std;
const int maxn=40,mod=998244353,inv10000=796898467,inv2=(mod+1)/2;
int n,m,ans,stp,tot,all;
int vis[maxn],f[maxn],mul[maxn*maxn],xx[maxn],yy[maxn],zz[maxn],id[maxn],g[maxn];
vector<int>v[maxn];
void dfs(int x){
	vis[x]=stp,id[x]=++tot;
	for(int i=0;i<v[x].size();i++)
		if(vis[v[x][i]]==0)
			dfs(v[x][i]);
}
int main(){
	mul[0]=1;
	for(int i=1;i<maxn*maxn;i++)
		mul[i]=1ll*mul[i-1]*inv2%mod;
	scanf("%d%d",&n,&m);
	all=1;
	for(int i=1;i<=n*(n-1);i++)
		all=10000ll*all%mod;
	for(int i=1,x,y,z;i<=m;i++)
		scanf("%d%d%d",&x,&y,&z),z=1ll*z*inv10000%mod,xx[i]=x,yy[i]=y,zz[i]=z,v[x].push_back(y),v[y].push_back(x);
	f[0]=1;
	for(int s=1;s<=n;s++)
		if(vis[s]==0){
			tot=0,stp++,dfs(s);
			for(int s=0;s<(1<<tot);s++){
				int mul=1;
				for(int i=1;i<=m;i++)
					if(vis[xx[i]]==stp&&vis[yy[i]]==stp&&((s>>(id[xx[i]]-1))&1)!=((s>>(id[yy[i]]-1))&1)){
						if((s>>(id[xx[i]]-1))&1)
							mul=2ll*mul*zz[i]%mod;
						else mul=2ll*mul*(1-zz[i]+mod)%mod;
					}
				for(int i=n;i>=__builtin_popcount(s);i--)
					g[i]=(g[i]+1ll*mul*f[i-__builtin_popcount(s)])%mod;
			}
			for(int i=0;i<=n;i++)
				f[i]=g[i],g[i]=0;
		}
	for(int i=0;i<n;i++)
		ans=(ans+1ll*f[i]*mul[i*(n-i)])%mod;
	printf("%d\n",1ll*ans*all%mod);
	return 0;
}

047 uoj#182. 【UR #12】a^-1 + b problem

很经典的处理方法,好像在洛谷月赛 Div2C 中见到过(((

可以发现,每个数 \(x\) 都能表示成 \(\frac{ax+b}{cx+d}\) 形式,其中 \(a,b,c,d\) 是与 \(x\) 无关的系数。

化简可变为 $$p+\frac{q}{x+k}$$,我们只需对于 \(m\)\(k\) 求出 \(\sum_{i=1}^n\frac{1}{a_i+k}\) 即可。

考虑:

\[\sum_{i=1}^n\frac{1}{a_i+k}=\frac{\sum_j\prod_{i\ne j}(a_i+k)}{\prod_{i=1}^n(a_i+k)} \]

下面是经典多项式多点求值,上面其实就是下面那个多项式求导,同样可以多点求值。

复杂度 \(O(n\log^2 n)\)

#include<stdio.h>
#include<vector>
#include<assert.h>
#define mid (l+r>>1)
#define lc(x) (x<<1)
#define rc(x) (x<<1|1)
using namespace std;
const int maxk=19,maxn=(1<<maxk),maxN=60005,mod=998244353,G=3,invG=(mod+1)/3;
int n,m,q;
int pt[maxN],ans[maxN],P[maxN],Q[maxN],id[maxN],a[maxn];
int ksm(int a,int b){
	int res=1;
	for(;b;a=1ll*a*a%mod,b>>=1)
		if(b&1)
			res=1ll*res*a%mod;
	return res;
}
namespace Polynomial{
	int btf[maxn],w[maxk+1][maxn][2],inv[maxn];
	typedef vector<int>poly;
	void init(){
		for(int len=2,i=1;i<=maxk;len<<=1,i++){
			int omega1=ksm(G,(mod-1)/len),omega2=ksm(invG,(mod-1)/len);
			w[i][0][0]=w[i][0][1]=1;
			for(int j=1;j<len;j++)
				w[i][j][0]=1ll*w[i][j-1][0]*omega1%mod,w[i][j][1]=1ll*w[i][j-1][1]*omega2%mod;
		}
		inv[1]=1;
		for(int i=2;i<maxn;i++)
			inv[i]=mod-1ll*(mod/i)*inv[mod%i]%mod;
	}
	int getlen(int n){
		int lim=1,r=0;
		while(lim<n)
			lim<<=1,r++;
		for(int i=0;i<lim;i++)
			btf[i]=(btf[i>>1]>>1)|((i&1)<<(r-1));
		return lim;
	}
	void NTT(poly &x,int lim,int opt){
		x.resize(lim);
		for(int i=0;i<lim;i++)
			if(i<btf[i])
				swap(x[i],x[btf[i]]);
		for(int len=2,now=1,p=1;len<=lim;len<<=1,now<<=1,p++)
			for(int i=0;i<lim;i+=len)
				for(int j=0;j<now;j++){
					int a=x[i+j],b=1ll*x[now+i+j]*w[p][j][opt]%mod;
					x[i+j]=(a+b)%mod,x[now+i+j]=(a-b+mod)%mod;
				}
		if(opt==0)
			for(int i=0;i<lim;i++)
				x[i]=1ll*x[i]*inv[lim]%mod;
	}
	poly operator*(poly a,poly b){
		int deg=a.size()+b.size()-1,lim=getlen(deg);
		poly c(lim);
		NTT(a,lim,1),NTT(b,lim,1);
		for(int i=0;i<lim;i++)
			c[i]=1ll*a[i]*b[i]%mod;
		NTT(c,lim,0),c.resize(deg);
		return c;
	}
	poly polyinv(poly x,int deg){
		poly res;
		if(deg==1){
			res.push_back(ksm(x[0],mod-2));
			return res;
		}
		poly a=x,b=polyinv(x,(deg+1)>>1);
		a.resize(deg);
		int lim=getlen(deg<<1);
		NTT(a,lim,1),NTT(b,lim,1);
		for(int i=0;i<lim;i++)
			res.push_back((2ll*b[i]-1ll*a[i]*b[i]%mod*b[i]%mod+mod)%mod);
		NTT(res,lim,0),res.resize(deg);
		return res;
	}
	poly polyrev(poly x){
		poly res;
		for(int i=x.size()-1;i>=0;i--)
			res.push_back(x[i]);
		return res;
	}
	poly polymod(poly a,poly b){
		if(b.size()>a.size())
			return a;
		int n=a.size(),m=b.size();
		poly ar=polyrev(a),br=polyrev(b);
		br.resize(n-m+2);
		poly c=polyinv(br,n-m+2),d=ar*c;
		d.resize(n-m+1);
		poly q=polyrev(d),bq=b*q;
		poly r;
		for(int i=0;i<m-1;i++)
			r.push_back((a[i]-bq[i]+mod)%mod);
		return r;
	}
};
using namespace Polynomial;
poly f,g,c[maxN<<2];
poly solve(int l,int r){
	if(l==r){
		poly res(2);
		res[0]=a[l],res[1]=1;
		return res;
	}
	return solve(l,mid)*solve(mid+1,r);
}
void solve1(int l,int r,int now){
	if(l==r){
		c[now].resize(2),c[now][0]=(mod-pt[l])%mod,c[now][1]=1;
		return ;
	}
	solve1(l,mid,lc(now)),solve1(mid+1,r,rc(now));
	c[now]=c[lc(now)]*c[rc(now)];
}
void solve2(int l,int r,int now,poly v,poly w){
	v=polymod(v,c[now]),w=polymod(w,c[now]);
	if(l==r){
		ans[id[l]]=1ll*w[0]*ksm(v[0],mod-2)%mod;
		return ;
	}
	solve2(l,mid,lc(now),v,w),solve2(mid+1,r,rc(now),v,w);
}
int main(){
	init();
	scanf("%d%d",&n,&m);
	int sum=0;
	for(int i=1;i<=n;i++)
		scanf("%d",&a[i]),sum=(sum+a[i])%mod;
	int a=1,b=0,c=0,d=1;
	for(int i=1,t,x;i<=m;i++){
		scanf("%d",&t);
		if(t==1)
			scanf("%d",&x),a=(a+1ll*x*c)%mod,b=(b+1ll*x*d)%mod;
		if(t==2)
			swap(a,c),swap(b,d);
		if(c){
			P[i]=1ll*n*a%mod*ksm(c,mod-2)%mod,Q[i]=1ll*(b-1ll*a*ksm(c,mod-2)%mod*d%mod+mod)*ksm(c,mod-2)%mod;
			id[++q]=i,pt[q]=1ll*d*ksm(c,mod-2)%mod;
		}
		else P[i]=(1ll*sum*a+1ll*n*b)%mod;
	}
	if(q){
		f=solve(1,n),solve1(1,q,1);
		g.resize(f.size()-1);
		for(int i=1;i<f.size();i++)
			g[i-1]=1ll*f[i]*i%mod;
		solve2(1,q,1,f,g);
	}
	for(int i=1;i<=m;i++)
		printf("%d\n",(int)((P[i]+1ll*Q[i]*ans[i])%mod));
	return 0;
}
posted @ 2022-07-25 11:14  xiaoziyao  阅读(47)  评论(0编辑  收藏  举报