1. 程式人生 > 其它 >Noip模擬91 2021.11.6

Noip模擬91 2021.11.6

T1 破門而入 T2 翻轉游戲 T3 奶油蛋糕塔 T4 多重影分身の術

T1 破門而入

第一類斯特林數前\(k\)項字首和

broken
#include<bits/stdc++.h>
#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<bits/stdc++.h>
#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<<ans-tot+1<<endl;
		return 0;
	}
}
signed main(){return WSN::main();}

T3 奶油蛋糕塔

考場上被這道題幹崩了,然後石樂志,這場考試就gg了

連邊找最大的有尤拉路的聯通塊,一個聯通塊的時候如果四個點都是奇數點就特判刪一條邊

儘量保證刪完邊後還是一個聯通塊

cake
#include<bits/stdc++.h>
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&&deg[fr]!=1&&deg[to]!=1)mn=min(mn,e[i].val);
			}
			cout<<ans-mn<<endl; return 0;
		}
		int ans=0;
		for(int i=1;i<=rp;i+=2){
			int fr=e[i].fr,to=e[i].to;
			fin[in[fr]]+=e[i].val;
		}
		for(int i=1;i<=cnt;i++)ans=max(ans,fin[i]);
		cout<<ans<<endl;
		return 0;
	}
}
signed main(){return WSN::main();}

T4 多重影分身の術

主角不是鳴人,直接就棄掉了

二分然後單指標掃進行\(check\),看看在二分出的時間內能否撿完全部卷軸即可

duplication
#include<bits/stdc++.h>
#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();}