……

ABC 167 A~F 题解

战况:\(100+200+300+400=1000\),时间 \(40:39\)\(rk\;1856\),new rating\(=202\)
感觉不错,但是仍然做不出 \(E,F\) 题。

下面是简要题解:

\(A.\)

题意概括:
问一个字符串能否通过在最后加一个字符构成另一个字符串。

暴力匹配即可:

char s1[15],s2[15];

int main()
{
	scanf("%s",s1);
	scanf("%s",s2);
	for(int i=0;i<strlen(s1);i++)
	{
		if(s1[i]==s2[i]) continue;
		else {printf("No\n");return 0;}
	}
	printf("Yes\n");
	return 0;	
}

\(B.\)

题意概括:
\(A\)\(1\)\(B\)\(0\)\(C\)\(-1\),问选 \(k\) 个得到的最大值。

贪心分类讨论即可:

int a,b,c,k;

int main()
{
	read(a),read(b),read(c),read(k);
	if(k<=a) printf("%d\n",k);
	else if(k<=a+b) printf("%d\n",a);
	else printf("%d\n",a-(k-a-b));
	return 0; 	
}

\(C.\)

题意概括:
\(n\) 本书,每本书对于 \(m\) 个技能熟练度有加成,问达到加成所需的值最少花多少钱。

发现 \(n\leqslant 12\),直接爆搜即可。
*,不好打,还不如直接状压,复杂度 \(\mathcal O(2^nnm)\)

int n,m,x;
int c[20],a[20][20];
int ans,now,f;
int rt[20];

int main()
{
	read(n),read(m),read(x);
	ans=inf;
	for(int i=1;i<=n;i++)
	{
		read(c[i]);
		for(int j=1;j<=m;j++)
		{
			read(a[i][j]);
		}	
	}
	for(int i=0;i<=(1<<n)-1;i++)
	{
		memset(rt,0,sizeof(rt));
		now=0;
		f=0;
		for(int j=0;j<=n-1;j++)
		{
			if(i&(1<<j))
			{
				now+=c[j+1];
				for(int k=1;k<=m;k++) rt[k]+=a[j+1][k];
			}
		}
		for(int j=1;j<=m;j++) if(rt[j]<x) f=1;
		if(!f) ans=min(ans,now); 
	}
	if(ans>2e9) printf("-1\n");
	else printf("%d\n",ans);
	return 0;
}

\(D.\)

题目描述:
每个地点有一个传送带,问传送 \(k\) 次到达的地点编号。

由于只有 \(n\leqslant 2*10^5\),容易想到有循环节,长度最大为 \(n\leqslant 2*10^5\)
那么判断每个出现的元素,然后记录循环开始的地点和区间长度,最后分类即可,复杂度 \(\mathcal O(n)\)

int n;
int a[200005];
ll k;
int rt[200005],cnt=0,p;
int b[200005],be,lo;

int main()
{
	read(n),readl(k);
	for(int i=1;i<=n;i++) read(a[i]);
	rt[0]=1,p=1,b[1]=0;
	while(1)
	{
		if(b[a[p]]!=0)
		{
			be=b[a[p]];
			lo=cnt-be+1;
			break;
		}
		rt[++cnt]=a[p];
		b[a[p]]=cnt;
		p=a[p];
	}
	if(k<=be) printf("%d\n",rt[k]);
	else
	{
		int s=(k-be)%lo;
		printf("%d\n",rt[s+be]);
	}
	return 0;
}

\(E.\)

题目简述:
\(n\) 个方格染 \(m\) 种颜色,要求最多有 \(k\) 组块相连且颜色相同,求方案数对 \(998244353\) 取模的结果。

组合数学,不会。

先上结论:

\[ans=\sum\limits_{i=0}^k mC_{n-1}^i(m-1)^{n-1-i} \]

感性理解:
先确定第一个块的的颜色,有 \(m\) 种方法,然后有 \(C_{n-1}^{n-1-i}=C_{n-1}^i\) 种将剩下的那些染成不同色,然后对于剩下的 \(n-i-1\) 块,每种都有 \(m-1\) 种颜色来涂。

为什么组合数不用卢卡斯,因为模数太大了......
复杂度为 \(\mathcal O(k\log n)\)

#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;

#define read(x) scanf("%d",&x)
#define MOD 998244353

int n,m,k;
int jc[200005];
int ans=0;

int quickpow(int a,int b)
{
	int ans=1,base=a;
	while(b)
	{
		if(b&1) ans=1ll*base*ans%MOD;
		b>>=1;
		base=1ll*base*base%MOD;
	}
	return ans%MOD;
}

void gjc(int n)
{
	jc[0]=1;
	for(int i=1;i<=n;i++) jc[i]=1ll*jc[i-1]*i%MOD;
	return;
}

int inv(int a){return quickpow(a,MOD-2);}

int C(int n,int m){return 1ll*jc[n]*inv(1ll*jc[m]*jc[n-m]%MOD)%MOD;}

int main()
{
	read(n),read(m),read(k);
	gjc(n);
	for(int i=0;i<=k;i++)
	{
		ans=(ans+1ll*m*C(n-1,i)%MOD*quickpow(m-1,n-i-1)%MOD)%MOD;
	}
	printf("%d\n",ans%MOD);
	return 0;
}

\(F.\)

题目简述:
给你 \(n\) 个括号串,问能否拼成一个合法的括号串。

我们发现只要合法,左括号能否匹配的右括号问题不大,要注意的是右括号的位置。

抽象一下,右括号消耗左括号。

同时,任何时候左括号的剩余数不能为负数。

那么我们考虑把左括号作为补充,右括号作为需求和削减,和这个题有很大的相似之处。

所以用栈模拟一下,把已经合法的子串去掉,然后排序即可。

至于原理,看那道题第一篇题解即可。

复杂度为 \(\mathcal O(\sum len)\)

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
using namespace std;

int n;
char s[1000005];
struct node1
{
	int a,b;
}x[1000005];
int cnt=0,c=0;
struct node2
{
	int a,b;
}y[1000005];
int st[1000005],top=0;
int sum=0,flag=0;

bool cmp1(node1 n,node1 m){return n.a+n.b>m.a+m.b;}
bool cmp2(node2 n,node2 m){return n.a<m.a;}

int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	{
		int now=0;
		top=0;
		scanf("%s",s);
		int len=strlen(s);
		for(int j=0;j<len;j++)
		{
			if(s[j]==')'&&!top) now++;
			else if(s[j]=='(') top++;
			else top--;
		}
		int s,t;
		if(now!=0) s=now,t=top-now;
		else s=0,t=top;
		if(t<0) x[++cnt].a=s,x[cnt].b=t;
		else y[++c].a=s,y[c].b=t;
	}
	sort(x+1,x+cnt+1,cmp1),sort(y+1,y+c+1,cmp2);
	for(int i=1;i<=c;i++)
	{
		if(sum<y[i].a) flag=1;
		sum+=y[i].b;
	}
	for(int i=1;i<=cnt;i++)
	{
		if(sum<x[i].a) flag=1;
		sum+=x[i].b;
	}
	if(flag||sum) printf("No\n");
	else printf("Yes\n");
	return 0;
}

终于线下阿克了一场 \(ABC\)

posted @ 2020-05-11 11:24  童话镇里的星河  阅读(392)  评论(0编辑  收藏  举报