Noip模拟91 2021.11.6


T1 破门而入

第一类斯特林数前\(k\)项前缀和

broken
#include
#define int long long
using namespace std;
const int NN=3005,mod=998244353;
namespace AE86{
	FILE *wsn;
	auto 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;
	};
	auto write=[](int x,char opt='\n'){
		char ch[20];short len=0;if(x<0)x=~x+1,putchar('-');
		do{ch[len++]=x%10+(1<<5)+(1<<4);x/=10;}while(x);
		for(short i=len-1;i>=0;--i){putchar(ch[i]);}putchar(opt);
	};
}using namespace AE86;
int n,k,dp[NN][NN];
namespace WSN{
	inline short main(){
		wsn=freopen("broken.in","r",stdin);
		wsn=freopen("broken.out","w",stdout);
		n=read();k=read();dp[0][0]=1;
		for(int i=1;i<=n;i++){
			for(int j=1;j<=i;j++){
				dp[i][j]=(dp[i-1][j]*(i-1)%mod+dp[i-1][j-1]%mod)%mod;
			}
		}
		int ans=0;
		for(int i=1;i<=k;i++) ans=(ans+dp[n][i])%mod;
		write(ans);
		return 0;
	}
}
signed main(){return WSN::main();}

T2 翻转游戏

开桶记录每个字符出现个数,然后选两个算重复的数量,拿总数一减就行

turn
#include
#define int long long
using namespace std;
const int NN=3e6+5;
FILE *wsn;
char s[NN];
int n,t[26],tot;
namespace WSN{
	inline short main(){
		wsn=freopen("turn.in","r",stdin);
		wsn=freopen("turn.out","w",stdout);
		scanf("%s",s+1);n=strlen(s+1);
		for(int i=1;i<=n;i++) ++t[s[i]-'a'];
		for(int i=0;i<26;i++) tot+=t[i]*(t[i]-1)/2;
		int ans=n*(n-1)/2;cout<

T3 奶油蛋糕塔

考场上被这道题干崩了,然后石乐志,这场考试就gg了

连边找最大的有欧拉路的联通块,一个联通块的时候如果四个点都是奇数点就特判删一条边

尽量保证删完边后还是一个联通块

cake
#include
using namespace std;
const int NN=5e5+5;
namespace AE86{
	FILE *wsn;
	auto 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;
	};
	auto write=[](int x,char opt='\n'){
		char ch[20];short len=0;if(x<0)x=~x+1,putchar('-');
		do{ch[len++]=x%10+(1<<5)+(1<<4);x/=10;}while(x);
		for(short i=len-1;i>=0;--i){putchar(ch[i]);}putchar(opt);
	};
}using namespace AE86;
int n,in[NN],cnt,deg[NN],fin[NN];
struct cake{int val,t1,t2;}c[NN];
struct SNOW{int fr,to,val,next;}e[NN<<1];int head[NN],rp;
auto add=[](int x,int y,int z){
	e[++rp]=SNOW{x,y,z,head[x]};head[x]=rp;
	e[++rp]=SNOW{y,x,z,head[y]};head[y]=rp;
};
char s[4];
#define star(i,x) for(int i=head[x],y=e[i].to;i;i=e[i].next,y=e[i].to)
inline void dfs(int x,int itin){
	if(in[x]) return; in[x]=itin;
	star(i,x) dfs(y,itin);
}
namespace WSN{
	inline short main(){
		wsn=freopen("cake.in","r",stdin);
		wsn=freopen("cake.out","w",stdout);
		n=read();
		for(int i=1;i<=n;i++){
			c[i].val=read();
			scanf("%s",s+1);c[i].t1=s[1]-'W';
			scanf("%s",s+1);c[i].t2=s[1]-'W';
			add(c[i].t1,c[i].t2,c[i].val);
			if(c[i].t1!=c[i].t2) ++deg[c[i].t1],++deg[c[i].t2];
		}
		for(int i=0;i<3;i++)if(!in[i])dfs(i,++cnt);
		if(cnt==1&&(deg[0]&1)&&(deg[1]&1)&&(deg[2]&1)&&(deg[3]&1)){
			int ans=0,mn=1e9;
			for(int i=1;i<=rp;i+=2){
				int fr=e[i].fr,to=e[i].to;
				ans+=e[i].val;
				if(fr!=to&°[fr]!=1&°[to]!=1)mn=min(mn,e[i].val);
			}
			cout<

T4 多重影分身の術

主角不是鸣人,直接就弃掉了

二分然后单指针扫进行\(check\),看看在二分出的时间内能否捡完全部卷轴即可

duplication
#include
#define int long long
using namespace std;
const int NN=3e5+5;
namespace AE86{
	FILE *wsn;
	auto 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;
	};
	auto write=[](int x,char opt='\n'){
		char ch[20];short len=0;if(x<0)x=~x+1,putchar('-');
		do{ch[len++]=x%10+(1<<5)+(1<<4);x/=10;}while(x);
		for(short i=len-1;i>=0;--i){putchar(ch[i]);}putchar(opt);
	};
}using namespace AE86;
int n,m,a[NN],b[NN];
inline int calc(int i,int l,int r){
	if(a[i]>=b[r]) return a[i]-b[l];
	if(a[i]<=b[l]) return b[r]-a[i];
	return b[r]-b[l]+min(b[r]-a[i],a[i]-b[l]);
}
inline bool check(int mid){
	int l=1,r=1;
	for(int i=1;i<=n;i++){
		while(calc(i,l,r)<=mid&&r<=m) ++r;
		if(r>m)return true;
		l=r;
	}
	return false;
}
namespace WSN{
	inline short main(){
		wsn=freopen("duplication.in","r",stdin);
		wsn=freopen("duplication.out","w",stdout);
		n=read(); m=read();
		for(int i=1;i<=n;i++) a[i]=read();
		for(int i=1;i<=m;i++) b[i]=read();
		sort(b+1,b+m+1); sort(a+1,a+n+1);
		int l=1,r=1e10,ans=1;
		while(l<=r){
			int mid=l+r>>1;
			if(check(mid)) r=mid-1,ans=mid;
			else l=mid+1;
		}
		write(ans);
		return 0;
	}
}
signed main(){return WSN::main();}