The 1st Universal Cup Stage 12: ̄Ookayama, April 15-16, 2023 题解

文章包含三个不同的算法问题:1)树上的最大黑色节点数问题,使用树DP解决;2)魔法钱包问题,通过直接模拟计算购买商品的最大数量;3)五组数据中位数问题,通过枚举和排序求解。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

A XOR Tree Path

给一颗树,树上点有黑白两色,每次可以选一个叶子节点,翻转其到根路径上所有点的颜色,问最大黑色点数。
树dp

#include<bits/stdc++.h> 
using namespace std;
#define MAXN (100000+10)
#define ll long long
#define F (100000000)
#define Rep(i,n) for(int i=0;i<n;i++)
#define next Next
int n,edge[MAXN*2],pre[MAXN],next[MAXN*2],Size=0;
int f[MAXN][2];
int a[MAXN];
int g[2];
void addedge(int u,int v)
{
	edge[++Size]=v;
	next[Size]=pre[u];
	pre[u]=Size;
}
void dfs(int x,int father)
{
	bool lef=1;
	int g[2];
	for (int p=pre[x];p;p=next[p])
	{
		int &v=edge[p];
		if (v!=father)
		{
			dfs(v,x);
			if(lef) {
				f[x][0]=g[0]=f[v][0];
				f[x][1]=g[1]=f[v][1];
				lef=0;
			}
			else {
				f[x][0]=max(g[0]+f[v][0],g[1]+f[v][1]);
				f[x][1]=max(g[1]+f[v][0],g[0]+f[v][1]);
				g[0]=f[x][0],g[1]=f[x][1];
			}
		}
	}	
	
	if(lef) f[x][0]=a[x],f[x][1]=a[x]^1;
	else f[x][0]+=a[x],f[x][1]+=a[x]^1;
}
int main()
{
//	freopen("a.in","r",stdin);
	scanf("%d",&n);
	memset(pre,0,sizeof(pre));
	memset(next,0,sizeof(next));
	for(int i=1;i<=n;i++) cin>>a[i];
	for (int i=1;i<n;i++)
	{
		int u,v;
		scanf("%d%d",&u,&v);
		addedge(u,v);addedge(v,u);
	}
	dfs(1,0);	
	cout<<max(f[1][0],f[1][1]);
	return 0;
}

B Magical Wallet

You have a magical wallet with X yen in it. (Yen is the currency of Japan.)
Using the magic on this wallet, you can rearrange the amount of money in the wallet as a decimal string
in any order you like. For example, if you have a magical wallet with 120 yen, you can use magic to change
the amount of money in the wallet to any of the following: 12 yen, 21 yen, 102 yen, 120 yen, 201 yen, or
210 yen (leading zeros are ignored).
You will now visit N shops with the magical wallet in order. At the i-th shop (1 ≤ i ≤ N ), a product
costing Ai yen is sold, and if the magical wallet contains at least Ai yen, you can pay Ai yen from the
magical wallet to buy the product.
You can use magic as much as you like whenever you want. How many products can you buy at most?

直接暴力模拟过程

#include<bits/stdc++.h> 
using namespace std;
#define For(i,n) for(int i=1;i<=n;i++)
#define Fork(i,k,n) for(int i=k;i<=n;i++)
#define ForkD(i,k,n) for(int i=n;i>=k;i--)
#define Rep(i,n) for(int i=0;i<n;i++)
#define ForD(i,n) for(int i=n;i;i--)
#define RepD(i,n) for(int i=n;i>=0;i--)
#define Forp(x) for(int p=pre[x];p;p=next[p])
#define Forpiter(x) for(int &p=iter[x];p;p=next[p])  
#define Lson (o<<1)
#define Rson ((o<<1)+1)
#define MEM(a) memset(a,0,sizeof(a));
#define MEMI(a) memset(a,0x3f,sizeof(a));
#define MEMi(a) memset(a,128,sizeof(a));
#define MEMx(a,b) memset(a,b,sizeof(a));
#define INF (0x3f3f3f3f)
#define F (1000000007)
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define vi vector<int> 
#define pi pair<int,int>
#define SI(a) ((a).size())
#define Pr(kcase,ans) printf("Case #%d: %lld\n",kcase,ans);
#define PRi(a,n) For(i,n-1) cout<<a[i]<<' '; cout<<a[n]<<endl;
#define PRi2D(a,n,m) For(i,n) { \
						For(j,m-1) cout<<a[i][j]<<' ';\
						cout<<a[i][m]<<endl; \
						} 
#pragma comment(linker, "/STACK:102400000,102400000")
#define ALL(x) (x).begin(),(x).end()
#define gmax(a,b) a=max(a,b);
#define gmin(a,b) a=min(a,b);
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
ll mul(ll a,ll b){return (a*b)%F;}
ll add(ll a,ll b){return (a+b)%F;}
ll sub(ll a,ll b){return ((a-b)%F+F)%F;}
void upd(ll &a,ll b){a=(a%F+b%F)%F;}
inline int read()
{
	int x=0,f=1; char ch=getchar();
	while(!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();}
	while(isdigit(ch)) { x=x*10+ch-'0'; ch=getchar();}
	return x*f;
} 
vi get(int x) {
	stringstream ss;
	ss<<x;
	char s[6];
	ss>>s;
	int m=strlen(s);
	vi v;
	sort(s,s+m);
	do{
		stringstream ss;
		ss<<s;
		int p;ss>>p;
		v.pb(p);
//		cout<<p<<" ";
	}while(next_permutation(s,s+m));
	return v;
}
#define MAXX (10000+10)
int f[101][MAXX];
vi v[MAXX];
int main()
{
//	freopen("B.in","r",stdin);
//	freopen(".out","w",stdout);
	int n,x;
	Rep(i,1e4) {
		v[i]=get(i);
	}
//	Rep(i,20) {
//		for(int j:v[i]) cout<<j<<' ';cout<<endl;
//	}
	cin>>n>>x;
	get(x);
	MEMi(f)
	for(int i:v[x])f[0][i]=0;
	Rep(i,n) {
		int cx=read();
		Rep(j,10000)gmax(f[i+1][j],f[i][j])
		Rep(j,10000) {
			if(f[i][j]>=0 && j>=cx) {
				for(int k:v[j-cx])
					gmax(f[i+1][k],f[i][j]+1)
			}
		}
	} 
	int t=0;
	Rep(j,10000) gmax(t,f[n][j])
	cout<<t<<endl;	
	return 0;
}

E Five Med Sum

在这里插入图片描述
枚举中位数,注意可以事先给A-E数组定个顺序,以防算重。

#include<bits/stdc++.h> 
using namespace std;
#define For(i,n) for(int i=1;i<=n;i++)
#define Fork(i,k,n) for(int i=k;i<=n;i++)
#define ForkD(i,k,n) for(int i=n;i>=k;i--)
#define Rep(i,n) for(int i=0;i<n;i++)
#define ForD(i,n) for(int i=n;i;i--)
#define RepD(i,n) for(int i=n;i>=0;i--)
#define Forp(x) for(int p=pre[x];p;p=next[p])
#define Forpiter(x) for(int &p=iter[x];p;p=next[p])  
#define Lson (o<<1)
#define Rson ((o<<1)+1)
#define MEM(a) memset(a,0,sizeof(a));
#define MEMI(a) memset(a,0x3f,sizeof(a));
#define MEMi(a) memset(a,128,sizeof(a));
#define MEMx(a,b) memset(a,b,sizeof(a));
#define INF (0x3f3f3f3f)
#define F (998244353)
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define vi vector<int> 
#define pi pair<int,int>
#define SI(a) ((a).size())
#define Pr(kcase,ans) printf("Case #%d: %lld\n",kcase,ans);
#define PRi(a,n) For(i,n-1) cout<<a[i]<<' '; cout<<a[n]<<endl;
#define PRi2D(a,n,m) For(i,n) { \
						For(j,m-1) cout<<a[i][j]<<' ';\
						cout<<a[i][m]<<endl; \
						} 
#pragma comment(linker, "/STACK:102400000,102400000")
#define ALL(x) (x).begin(),(x).end()
#define gmax(a,b) a=max(a,b);
#define gmin(a,b) a=min(a,b);
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
ll mul(ll a,ll b){return (a*b)%F;}
ll add(ll a,ll b){return (a+b)%F;}
ll sub(ll a,ll b){return ((a-b)%F+F)%F;}
void upd(ll &a,ll b){a=(a%F+b%F)%F;}
inline int read()
{
	int x=0,f=1; char ch=getchar();
	while(!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();}
	while(isdigit(ch)) { x=x*10+ch-'0'; ch=getchar();}
	return x*f;
} 
//class node{
//	int x,t;
//	bool friend operator<(node a,node b) {
//		if(a.x<b.x)
//	}
//};
vector<pair<int,int > > v[5];
int main()
{
//	freopen("E.in","r",stdin);
//	freopen(".out","w",stdout);
	int n=read();
	Rep(j,5) {
		For(i,n) v[j].pb(mp(read(),j) );
		sort(ALL(v[j]));
	}
	ll ans=0;
	Rep(j,5) {
		Rep(i,n) {
			int p=v[j][i].fi;
			vi L,R;
			
			Rep(k,5) if(k^j) {
				int l=lower_bound(ALL(v[k]),v[j][i])-v[k].begin();
				int r=v[k].end()-lower_bound(ALL(v[k]),v[j][i]);
				L.pb(l),R.pb(r);
			}
			Rep(p1,3) Fork(p2,p1+1,3) {
				ll c=mul(L[p1],L[p2]);
				Rep(t,4) if(t!=p1 && t!=p2) c=mul(c,R[t]);
				upd(ans,mul(c,p));
			}
		}
	}
	cout<<ans;
	return 0;
}

### 电路设计与实现 RS触发器是一种基本的时序逻辑电路,能够存储一位二进制信息。使用NAND门可以构建基本RS触发器,并通过真值表验证其逻辑关系。 #### RS触发器真值表(基于NAND门) 当使用NAND门构建基本RS触发器时,输入信号S和R为低电平有效(即负逻辑),因此真值表略有不同。以下是基于NAND门的RS触发器真值表: | S | R | Q(t+1) | /Q(t+1) | |---|---|--------|---------| | 0 | 0 | 不允许 | 不允许 | | 0 | 1 | 1 | 0 | | 1 | 0 | 0 | 1 | | 1 | 1 | Q(t) | /Q(t) | 其中,Q(t)表示当前状态,Q(t+1)表示下一状态。当S=0且R=0时,触发器处于不允许的状态;当S=0且R=1时,触发器被置位(Q=1);当S=1且R=0时,触发器被复位(Q=0);当S=1且R=1时,触发器保持原来的状态[^1]。 #### 使用NAND门设计RS触发器 RS触发器可以通过两个交叉连接的NAND门实现。具体电路图如下: ``` +---+ S ----| | |NAND|---- Q R ----| | +---+ +---+ Q ----| | |NAND|---- /Q /Q ---| | +---+ ``` 在该电路中,S和R是输入信号,Q和/Q是输出信号。通过改变S和R的电平,可以控制触发器的状态[^1]。 #### 实验结果展示 当S=0且R=1时,触发器被置位,Q=1,/Q=0;当S=1且R=0时,触发器被复位,Q=0,/Q=1;当S=1且R=1时,触发器保持原来的状态;当S=0且R=0时,触发器处于不允许的状态,Q和/Q的状态不确定[^1]。 以下是一个简单的Verilog代码示例,用于模拟基于NAND门的RS触发器的行为: ```verilog module rs_flip_flop(input S, R, output reg Q, output reg Q_bar); always @(S or R) begin if (S == 0 && R == 0) begin // 不允许状态 Q = 1'bx; Q_bar = 1'bx; end else if (S == 0) begin // 置位 Q = 1; Q_bar = 0; end else if (R == 0) begin // 复位 Q = 0; Q_bar = 1; end else begin // 保持状态 Q = Q; Q_bar = Q_bar; end end endmodule ``` 测试平台代码如下: ```verilog module testbench; reg S, R; wire Q, Q_bar; rs_flip_flop uut ( .S(S), .R(R), .Q(Q), .Q_bar(Q_bar) ); initial begin // 测试用例 S = 1; R = 1; #10; S = 0; R = 1; #10; S = 1; R = 0; #10; S = 0; R = 0; #10; $finish; end endmodule ``` 通过仿真工具运行上述代码,可以观察到输出信号Q和/Q的变化情况,从而验证RS触发器的功能[^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值