2021.9.26考试总结[NOIP模拟62]

T1 set

\(0\)\(n\)前缀余数有\(n+1\)个,但只有\(n\)种取值,找到一样的两个输出区间即可。

\(code:\)

T1
#include<bits/stdc++.h>
using namespace std;

namespace IO{
	inline int read(){
		char ch=getchar(); int x=0,f=1;
		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;
	}
	inline void write(int x,char sp){
		char ch[20]; int len=0;
		if(x<0){ putchar('-'); x=~x+1; }
		do{ ch[len++]=(1<<4)+(1<<5)+x%10; x/=10; }while(x);
		for(int i=len-1;~i;--i) putchar(ch[i]); putchar(sp);
	}
	inline int max(int x,int y){ return x<y?y:x; }
	inline int min(int x,int y){ return x<y?x:y; }
	inline void swap(int& x,int& y){ x^=y^=x^=y; }
	inline void ckmax(int& x,int y){ x=x<y?y:x; }
	inline void ckmin(int& x,int y){ x=x<y?x:y; }
} using namespace IO;

const int NN=1000010;
int n,a[NN],pre[NN],sum[NN];

signed main(){
	freopen("a.in","r",stdin);
	freopen("a.out","w",stdout);
	n=read(); 
	for(int i=1;i<=n;i++) pre[i]=-1;
	for(int i=1;i<=n;i++)
		a[i]=read()%n;
	for(int i=1;i<=n;i++){
		sum[i]=(sum[i-1]+a[i])%n;
		if(pre[sum[i]]>=0){
			write(i-pre[sum[i]],'\n');
			for(int j=pre[sum[i]]+1;j<=i;j++)
				write(j,' ');
			return 0;
		}
		pre[sum[i]]=i;
	}
	puts("-1");
	return 0;
}

T2 read

答案为\(max(0,maxa*2-n-1)\)。发现我们只关心大于一半的最大值。在生成\(a\)时记\(id\)\(cnt\)\(cnt\)为零时将\(id\)赋为当前的\(a\),否则如果当前\(a\)\(id\)相同则令\(cnt\)加一,反之减一。如果最大值大于一半,最终\(id\)肯定为最大值且\(cnt\)大于零。再扫一遍即可。

值域是\(1e9\),也可开\(1e5\)的桶,先将\(1e9\)分为\(1e4\)\(1e5\),统计个数最多的区间,再在这个区间里单个统计最大值。(%%\(fengwu\)

\(code:\)

T2
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;

namespace IO{
	inline int read(){
		char ch=getchar(); int x=0,f=1;
		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;
	}
	inline void write(int x,char sp){
		char ch[20]; int len=0;
		if(x<0){ putchar('-'); x=~x+1; }
		do{ ch[len++]=(1<<4)+(1<<5)+x%10; x/=10; }while(x);
		for(int i=len-1;~i;--i) putchar(ch[i]); putchar(sp);
	}
	inline int max(int x,int y){ return x<y?y:x; }
	inline int min(int x,int y){ return x<y?x:y; }
	inline void swap(int& x,int& y){ x^=y^=x^=y; }
	inline void ckmax(int& x,int y){ x=x<y?y:x; }
	inline void ckmin(int& x,int y){ x=x<y?x:y; }
} using namespace IO;

const int NN=1010;
int n,s,m,k,id,cnt,sum,x[NN],y[NN],z[NN],Cnt[NN];
LL last;

signed main(){
	freopen("b.in","r",stdin);
	freopen("b.out","w",stdout);
	m=read(); k=read(); s=(1<<k)-1;
	for(int i=1;i<=m;i++) sum+=(Cnt[i]=read());
	for(int i=1;i<=m;i++) x[i]=read();
	for(int i=1;i<=m;i++) y[i]=read();
	for(int i=1;i<=m;i++) z[i]=read();
	for(int i=1;i<=m;i++){
		last=x[i];
		if(!cnt) id=last, ++cnt;
		else if(id!=last) --cnt;
		else ++cnt;
		for(int j=1;j<Cnt[i];j++){
			last=(last*y[i]+z[i])&s;
			if(!cnt) id=last, ++cnt;
			else if(id!=last) --cnt;
			else ++cnt;
		}
	}
	if(cnt<=0){ puts("0"); return 0; }
	cnt=0;
	for(int i=1;i<=m;i++){
		last=x[i];
		if(last==id) ++cnt;
		for(int j=1;j<Cnt[i];j++){
			last=(last*y[i]+z[i])&s;
			if(last==id) ++cnt;
		}
	}
	write(max(cnt*2-sum-1,0),'\n');
	return 0;
}

T3 题目交流通道

\(d\)不为零时可跑\(floyd\)。如果有\(k\)满足\(d_{u,v}=d_{u,k}+d_{k,v}\),则\(u,v\)之间的边取值随意,只要不小于\(d_{u,v}\)即可。

考虑\(d\)为零时,image

\(code:\)

T3
#include<bits/stdc++.h>
#define int long long
using namespace std;

namespace IO{
	inline int read(){
		char ch=getchar(); int x=0,f=1;
		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;
	}
	inline void write(int x,char sp){
		char ch[20]; int len=0;
		if(x<0){ putchar('-'); x=~x+1; }
		do{ ch[len++]=(1<<4)+(1<<5)+x%10; x/=10; }while(x);
		for(int i=len-1;~i;--i) putchar(ch[i]); putchar(sp);
	}
	inline int max(int x,int y){ return x<y?y:x; }
	inline int min(int x,int y){ return x<y?x:y; }
	inline void swap(int& x,int& y){ x^=y^=x^=y; }
	inline void ckmax(int& x,int y){ x=x<y?y:x; }
	inline void ckmin(int& x,int y){ x=x<y?x:y; }
} using namespace IO;

const int NN=410,p=998244353;
int n,k,ans,g[NN],f[NN],d[NN][NN],dis[NN][NN];
bool nul[NN][NN],vis[NN][NN];

namespace combination{
	int fac[NN],inv[NN];
	inline int C(int n,int m){ return n<m?0:fac[n]*inv[m]%p*inv[n-m]%p; }
	int qpow(int a,int b){
		int res=1;
		while(b){
			if(b&1) res=res*a%p;
			a=a*a%p;
			b>>=1;
		}
		return res;
	}
	void init(){
		fac[0]=inv[0]=f[1]=1;
		for(int i=1;i<=n;i++) fac[i]=fac[i-1]*i%p;
		inv[n]=qpow(fac[n],p-2);
		for(int i=n-1;i;i--) inv[i]=inv[i+1]*(i+1)%p;
		for(int i=1;i<=n;i++)
			g[i]=qpow(k+1,C(i,2));
		int sum=0;
		for(int i=2;i<=n;i++){
			f[i]=g[i];
			for(int j=1;j<i;j++)
				f[i]=(p+f[i]-f[j]*g[i-j]%p*C(i-1,j-1)%p*qpow(k,j*(i-j))%p)%p;
		}
	}
} using namespace combination;

namespace DSU{
	int fa[NN],siz[NN];
	int getf(int x){ 
		return fa[x]==x?x:fa[x]=getf(fa[x]);
	}
	void prework(){
		for(int i=1;i<=n;i++)
			fa[i]=i, siz[i]=1;
	}
	void merge(int x,int y){
		x=getf(x); y=getf(y);
		if(x==y) return;
		siz[x]+=siz[y];
		fa[y]=x;
	}
} using namespace DSU;

namespace work{
	void judge(){
		for(int i=1;i<=n;i++){
			if(d[i][i])
				puts("0"),exit(0);
			for(int j=1;j<=n;j++)
				if(d[i][j]!=d[j][i]||d[i][j]>k)
					puts("0"),exit(0);
		}
		for(int k=1;k<=n;k++)
			for(int i=1;i<=n;i++)
				for(int j=1;j<=n;j++)
					if(d[i][j]>d[i][k]+d[k][j])
						puts("0"),exit(0);
	}
	int getans(){
		int res=1,tmp=1;
		for(int i=1;i<=n;i++) if(getf(i)==i)
			res=res*f[siz[i]];
		for(int i=1;i<=n;i++) if(getf(i)==i)
			for(int j=i+1;j<=n;j++) if(getf(j)==j)
				if(nul[i][j]) tmp=tmp*qpow(k-d[i][j]+1,siz[i]*siz[j])%p;
				else tmp=tmp*(p+qpow(k-d[i][j]+1,siz[i]*siz[j])-qpow(k-d[i][j],siz[i]*siz[j]))%p;
		return res*tmp%p;
	}
} using namespace work;

signed main(){
	freopen("c.in","r",stdin);
	freopen("c.out","w",stdout);
	n=read(); k=read(); ans=1;
	for(int i=1;i<=n;i++)
		for(int j=1;j<=n;j++)
			d[i][j]=read();
	init(); prework(); judge();
	for(int i=1;i<n;i++)
		for(int j=i+1;j<=n;j++)
			if(!d[i][j]) merge(i,j);
	for(int fk,k=1;k<=n;k++){
		fk=getf(k);
		for(int fi,i=1;i<=n;i++){
			fi=getf(i);
			for(int fj,j=1;j<=n;j++){
				fj=getf(j);
				if(fi==fj||fj==fk||fi==fk) continue;
				if(d[i][j]==d[i][k]+d[k][j]) nul[fi][fj]=1;
			}
		}
	}
	write(getans(),'\n');
	return 0;
}
posted @ 2021-09-27 06:32  keen_z  阅读(47)  评论(0编辑  收藏  举报