CSP 模拟 1

T1 [start]

原题 P7506 「Wdsr-2.5」琪露诺的算数游戏
大模拟,写完只贴个代码。

点击查看代码
#include<bits/stdc++.h>
typedef long long ll;
typedef unsigned long long ull;
inline int read(){char ch=getchar();int x=0,f=1;for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;for(;ch>='0'&&ch<='9';ch=getchar())x=(x<<3)+(x<<1)+(ch^48);return x*f;}
const int N=105;
int n,m,k,st,top,tag,now,end,P,R;
std::string sk[(int)3e5+10];
inline int SK(std::string s){
	if(s.size()==2){return s[1]-'0';}
	else {return (s[1]-'0')*10+s[2]-'0';}
}
inline int ne(int x){return ((x+tag+n)%n)?((x+tag+n)%n):n;}
struct PEO{std::string name,c[4];int tag;}p[N];
inline void useno(int id){
	int max=-1e9;
	for(int i=1;i<=3;++i){
		if(p[id].c[i].size()<=3){
			int x=SK(p[id].c[i]);
			if(p[id].c[i][0]=='A'){
				x+=P;
				if(x<=99)max=std::max(x,max);
			}if(p[id].c[i][0]=='B'){
				x=P-x;
				if(x<=99)max=std::max(x,max);
			}if(p[id].c[i][0]=='C'){
				x=P*x;
				if(x<=99)max=std::max(x,max);
			}if(p[id].c[i].size()<=3&&p[id].c[i][0]=='D'){
				x=std::floor(P*1.0/x);
				if(x<=99)max=std::max(x,max);
			}if(p[id].c[i][0]=='E'){
				max=std::max(x,max);
			}
		}
	}
	if(max==-1e9){
		for(int i=1;i<=3;++i){
			if(p[id].c[i]=="PASS"){
				std::cout<<p[id].name<<" used PASS,now p="<<P<<".\n";
				p[id].c[i]=sk[top++];
				return;
			}
		}
		for(int i=1;i<=3;++i){
			if(p[id].c[i]=="TURN"){
				std::cout<<p[id].name<<" used TURN,now p="<<P<<".\n";
				tag*=-1;
				p[id].c[i]=sk[top++];
				return;
			}
		}
		for(int i=1;i<=3;++i){
			if(p[id].c[i]=="DOUBLE"){
				std::cout<<p[id].name<<" used DOUBLE,now p="<<P<<".\n";
				p[ne(now)].tag=1;
				p[id].c[i]=sk[top++];
				return;
			}
		}
		std::cout<<p[id].name<<" lost the game.\n";
		p[id].c[1]=sk[top++];p[id].c[2]=sk[top++];p[id].c[3]=sk[top++];
		end=1;
		return;
	}
	int pd=0;
	for(int i=1;i<=3;++i){
		int x=SK(p[id].c[i]);
		if(p[id].c[i][0]=='C'){
			x=P*x;
			if(x==max){
				P=x;
				std::cout<<p[id].name<<" used "<<p[id].c[i]<<",now p="<<P<<".\n";
				p[id].c[i]=sk[top++];
				p[id].tag=0;
				pd=1;
				return;
			}
		}
	}
	if(!pd){
		for(int i=1;i<=3;++i){
			int x=SK(p[id].c[i]);
			if(p[id].c[i][0]=='A'){
				x=P*1.0+x;
				if(x==max){
					P=x;
					std::cout<<p[id].name<<" used "<<p[id].c[i]<<",now p="<<P<<".\n";
					p[id].c[i]=sk[top++];
					p[id].tag=0;
					pd=1;
					return;
				}
			}
		}
	}
	if(!pd){
		for(int i=1;i<=3;++i){
			int x=SK(p[id].c[i]);
			if(p[id].c[i][0]=='B'){
				x=P-x;
				if(x==max){
					P=x;
					std::cout<<p[id].name<<" used "<<p[id].c[i]<<",now p="<<P<<".\n";
					p[id].c[i]=sk[top++];
					p[id].tag=0;
					pd=1;
					return;
				}
			}
		}
	}
	if(!pd){
		for(int i=1;i<=3;++i){
			int x=SK(p[id].c[i]);
			if(p[id].c[i].size()<=3&&p[id].c[i][0]=='D'){
				x=std::floor(P*1.0/x);
				if(x==max){
					P=x;
					std::cout<<p[id].name<<" used "<<p[id].c[i]<<",now p="<<P<<".\n";
					p[id].c[i]=sk[top++];
					p[id].tag=0;
					pd=1;
					return;
				}
			}
		}
	}
	if(!pd){
		for(int i=1;i<=3;++i){
			int x=SK(p[id].c[i]);
			if(p[id].c[i][0]=='E'){
				if(x==max){
					P=x;
					std::cout<<p[id].name<<" used "<<p[id].c[i]<<",now p="<<P<<".\n";
					p[id].c[i]=sk[top++];
					p[id].tag=0;
					return;
				}
			}
		}
	}
}
inline void use(int id){
	if(p[id].tag){
		for(int i=1;i<=3;++i){
			if(p[id].c[i]=="PASS"){
				std::cout<<p[id].name<<" used PASS,now p="<<P<<".\n";
				p[id].c[i]=sk[top++];
				p[id].tag=0;
				p[ne(now)].tag=1;
				return;
			}
		}
		for(int i=1;i<=3;++i){
			if(p[id].c[i]=="TURN"){
				std::cout<<p[id].name<<" used TURN,now p="<<P<<".\n";
				tag*=-1;
				p[id].c[i]=sk[top++];
				p[id].tag=0;
				p[ne(now)].tag=1;
				return;
			}
		}
		for(int i=1;i<=3;++i){
			if(p[id].c[i]=="DOUBLE"){
				std::cout<<p[id].name<<" used DOUBLE,now p="<<P<<".\n";
				p[ne(now)].tag=1;
				p[id].c[i]=sk[top++];
				p[id].tag=0;
				return;
			}
		}
		int min=100;
		for(int i=1;i<=3;++i){
			if(p[id].c[i].size()<=3){
				int x=SK(p[id].c[i]);
				if(p[id].c[i][0]=='A'){
					x+=P;
					if(x<=99)min=std::min(x,min);
				}if(p[id].c[i][0]=='B'){
					x=P-x;
					if(x<=99)min=std::min(x,min);
				}if(p[id].c[i][0]=='C'){
					x=P*x;
					if(x<=99)min=std::min(x,min);
				}if(p[id].c[i].size()<=3&&p[id].c[i][0]=='D'){
					x=std::floor(P*1.0/x);
					if(x<=99)min=std::min(x,min);
				}if(p[id].c[i][0]=='E'){
					min=std::min(x,min);
				}
			}
		}
		if(min>99){
			std::cout<<p[id].name<<" lost the game.\n";
			p[id].c[1]=sk[top++];p[id].c[2]=sk[top++];p[id].c[3]=sk[top++];
			end=1;
			return ;
		}
		int pd=0;
		for(int i=1;i<=3;++i){
			int x=SK(p[id].c[i]);
			if(p[id].c[i].size()<=3&&p[id].c[i][0]=='D'){
				x=std::floor(P*1.0/x);
				if(x==min){
					P=x;
					std::cout<<p[id].name<<" used "<<p[id].c[i]<<",now p="<<P<<".\n";
					p[id].c[i]=sk[top++];
					p[id].tag=0;
					pd=1;
					break;
				}
			}
		}
		if(!pd){
			for(int i=1;i<=3;++i){
				int x=SK(p[id].c[i]);
				if(p[id].c[i][0]=='B'){
					x=P-x;
					if(x==min){
						P=x;
						std::cout<<p[id].name<<" used "<<p[id].c[i]<<",now p="<<P<<".\n";
						p[id].c[i]=sk[top++];
						p[id].tag=0;
						pd=1;
						break;
					}
				}
			}
		}
		if(!pd){
			for(int i=1;i<=3;++i){
				int x=SK(p[id].c[i]);
				if(p[id].c[i][0]=='A'){
					x=P*1.0+x;
					if(x==min){
						P=x;
						std::cout<<p[id].name<<" used "<<p[id].c[i]<<",now p="<<P<<".\n";
						p[id].c[i]=sk[top++];
						p[id].tag=0;
						pd=1;
						break;
					}
				}
			}
		}
		if(!pd){
			for(int i=1;i<=3;++i){
				int x=SK(p[id].c[i]);
				if(p[id].c[i][0]=='C'){
					x=P*x;
					if(x==min){
						P=x;
						std::cout<<p[id].name<<" used "<<p[id].c[i]<<",now p="<<P<<".\n";
						p[id].c[i]=sk[top++];
						p[id].tag=0;
						pd=1;
						break;
					}
				}
			}
		}
		if(!pd){
			for(int i=1;i<=3;++i){
				int x=SK(p[id].c[i]);
				if(p[id].c[i][0]=='E'){
					if(x==min){
						P=x;
						std::cout<<p[id].name<<" used "<<p[id].c[i]<<",now p="<<P<<".\n";
						p[id].c[i]=sk[top++];
						p[id].tag=0;
						break;
					}
				}
			}
		}
		useno(id);
	}else{useno(id);}
}
signed main(){
	// freopen("P7506_10.in","r",stdin);freopen("out.out","w",stdout);
	std::ios::sync_with_stdio(false);std::cin.tie(0);std::cout.tie(0);
	std::cin>>n>>m>>k;
	for(int i=1;i<=n;++i)std::cin>>p[i].name>>p[i].c[1]>>p[i].c[2]>>p[i].c[3];
	for(int i=1;i<=k;++i)std::cin>>sk[++top];
	top=1;tag=1;now=1;
	for(int i=1;i<=m;++i){
		std::cout<<"Round "<<i<<":"<<'\n';
		while(1){
			use(now);
			if(end){
				end=0;tag=1;P=0;
				for(int j=1;j<=n;++j)p[j].tag=0;
				break;
			}
			now=ne(now);
		}
	}
}
妈了,题读不对,选完之后没标记又选调半天。红温。

T2 mine (CF404D Minesweeper 1D )

\(0,1,2,3\) 分别表示周围 \(0\) 个雷,\(1\) 个雷,\(2\) 个雷,自己是雷。
\(f[i][j][k]\) 表示到第 \(i\) 个数,前 \(i-2\) 个数合法且第 \(i-1\) 个数为 \(j\),第 \(i\) 个数为 \(k\) 的方案数。
特别的,\(f[i][0][0]\) 表示第 \(i\) 位是 \(0\) 的方案数。显然有状态转移方程:

\[\begin{aligned} \begin{cases} &f[i][0][0]=f[i-1][0][0]+f[i-1][3][1]\\ &f[i][0][1]=f[i-1][0][0]\\ &f[i][1][1]=f[i-1][3][1]\\ &f[i][3][1]=f[i-1][1][3]+f[i-1][2][3]+f[i-1][3][3]\\ &f[i][3][2]=f[i-1][1][3]+f[i-1][2][3]+f[i-1][3][3]\\ &f[i][1][3]=f[i-1][0][1]+f[i-1][1][1]\\ &f[i][2][3]=f[i-1][3][2]\\ &f[i][3][3]=f[i-1][1][3]+f[i-1][2][3]+f[i-1][3][3] \end{cases} \end{aligned} \]

一些非法状态不需要考虑。

点击查看代码
#include<bits/stdc++.h>
#define int long long
typedef long long ll;
typedef unsigned long long ull;
inline int read(){char ch=getchar();int x=0,f=1;for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;for(;ch>='0'&&ch<='9';ch=getchar())x=(x<<3)+(x<<1)+(ch^48);return x*f;}
const int N=1e6+10,mod=1e9+7;
char s[N];
int a[N],f[N][4][4];
inline int mo(int x){return x<0?(x%mod+mod)%mod:(x>=mod?x%mod:x);}
signed main(){
	// freopen("in.in","r",stdin);freopen("out.out","w",stdout);
	std::ios::sync_with_stdio(false);std::cin.tie(0);std::cout.tie(0);
	std::cin>>s+1;
	int n=strlen(s+1);
	for(int i=1;i<=n;++i){
		a[i]=s[i]-'0';
		if(s[i]=='*')a[i]=3;
		if(s[i]=='?')a[i]=4;
	}
	if(!a[1]||a[1]==4){
		f[1][0][0]=1;
	}if(a[1]==1||a[1]==4){
		f[1][0][1]=1;
	}if(a[1]==3||a[1]==4){
		f[1][1][3]=1;
	}
	for(int i=2;i<=n;++i){
		if(!a[i]||a[i]==4){
			f[i][0][0]=mo(f[i-1][0][0]+f[i-1][3][1]);
		}
		if(a[i]==1||a[i]==4){
			f[i][0][1]=f[i-1][0][0];
			f[i][1][1]=f[i-1][3][1];
			f[i][3][1]=mo(f[i-1][1][3]+f[i-1][2][3]+f[i-1][3][3]);
		}
		if(a[i]==2||a[i]==4){
			f[i][3][2]=mo(f[i-1][1][3]+f[i-1][2][3]+f[i-1][3][3]);
		}
		if(a[i]==3||a[i]==4){
			f[i][1][3]=mo(f[i-1][0][1]+f[i-1][1][1]);
			f[i][2][3]=f[i-1][3][2];
			f[i][3][3]=mo(f[i-1][1][3]+f[i-1][2][3]+f[i-1][3][3]);
		}
	}
	std::cout<<mo(f[n][0][0]+f[n][3][1]+f[n][1][3]+f[n][2][3]+f[n][3][3])<<'\n';
}

T3 小凯的疑惑

根据裴蜀定理,不定方程 \(ax+by=sum\),当且仅当 \(\gcd(x,y)\mid sum\) 时有解,所以不互质的直接判就行。
对于互质的,\(kx\bmod y\) 组成了 \(y\) 的完系,所以当余数 \(p\) 出现后,所有的 \(ans \bmod y=p\) 都是非法的。因为它一定可以表示为 \(ax+by\) 的形式,只需要在 \(ax\) 前添若干个 \(y\) 即可。
所以对于每一个余数考虑,假设 \(kx\bmod y=p\),对于所有的 \(ans \bmod y=p\) 只有在余数 \(p\) 第一次出现之前的合法,所以考虑有多少个 \(y\)\(kx\) 之前,即 \(\left[0,\left\lfloor\frac{kx}{y}\right\rfloor-1\right]\),有 \(\left\lfloor\frac{kx}{y}\right\rfloor\) 种。
所以最后就是求这个

\[\begin{aligned} \sum_{i=0}^{y-1}\left\lfloor\frac{ix}{y}\right\rfloor&=\sum_{i=0}^{y-1}\frac{ix-(ix\bmod y)}{y}\\ &=\sum_{i=0}^{y-1}\frac{ix}{y}-\sum_{i=0}^{y-1}\frac{i}{y}\\ &=\sum_{i=0}^{y-1}\frac{i(x-1)}{y}\\ &=(x-1)\sum_{i=0}^{y-1}\frac{i}{y}\\ &=\frac{(x-1)(y-1)}{2} \end{aligned} \]

赛时写了 \(\mathcal{O}(n)\),逆天评测机还没本地快,一秒跑不了裸的 2e8,把循环展开就过了,把 \(2\) 的常数消了也过了,就是赛时过不了,挂了 90,300->210,喃泵。

T4 春节十二响

首先考虑策略,对于一条链的,显然是将左右两边候选的排好序后,贪心的大的匹配大的,小的匹配小的。很容易扩展到树上。
考虑对于每一个节点建立一个优先队列 \(q_i\),对于一个节点就是将它的儿子的优先队列一一合并,最后将当前点加入到合并后的优先队列中。
正确性比较显然,但是时间复杂度是可以卡到 \(\mathcal{O}(n^2\log n)\) 的,发现有很多东西不必重建,只需要继承即可,并且显然可以启发式合并。
具体来说,用 \(po_i\) 表示节点 \(i\) 指向的优先队列编号,合并过程中实时更新,尽量让小去合并大。因为这题每个点都只会进出一次,所以时间复杂度是 \(\mathcal{O}(n\log n)\)

点击查看代码
#include<bits/stdc++.h>
#define int long long
typedef long long ll;
typedef unsigned long long ull;
inline int read(){char ch=getchar();int x=0,f=1;for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;for(;ch>='0'&&ch<='9';ch=getchar())x=(x<<3)+(x<<1)+(ch^48);return x*f;}
const int N=2e5+10;
int n,w[N],po[N];
std::vector<int> e[N],v1,v2,v3;
std::priority_queue<int> q[N];
inline void dfs(int u){
	for(int v:e[u]){
		dfs(v);
		int l=po[u],r=po[v];
		if(q[l].size()<q[r].size()){std::swap(po[u],po[v]),std::swap(l,r);}
		while(!q[l].empty()&&!q[r].empty()){
			int x=q[l].top(),y=q[r].top();q[l].pop(),q[r].pop();
			v3.push_back(std::max(x,y));
		}
		for(int x:v3)q[l].push(x);
		v3.clear();
	}
	q[po[u]].push(w[u]);
}
signed main(){
	// freopen("in.in","r",stdin);freopen("out.out","w",stdout);
	std::ios::sync_with_stdio(false);std::cin.tie(0);std::cout.tie(0);
	n=read();
	for(int i=1;i<=n;++i)po[i]=i;
	for(int i=1;i<=n;++i)w[i]=read();
	for(int i=2;i<=n;++i){
		e[read()].push_back(i);
	}
	dfs(1);
	int ans=0;
	while(!q[po[1]].empty()){
		ans+=q[po[1]].top();q[po[1]].pop();
	}
	std::cout<<ans<<'\n';
}
posted @ 2024-07-18 16:26  Ishar-zdl  阅读(67)  评论(6)    收藏  举报