zoukankan      html  css  js  c++  java
  • 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
    ");return 0;}
    	}
    	printf("Yes
    ");
    	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
    ",k);
    	else if(k<=a+b) printf("%d
    ",a);
    	else printf("%d
    ",a-(k-a-b));
    	return 0; 	
    }
    

    (C.)

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

    发现 (nleqslant 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
    ");
    	else printf("%d
    ",ans);
    	return 0;
    }
    

    (D.)

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

    由于只有 (nleqslant 2*10^5),容易想到有循环节,长度最大为 (nleqslant 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
    ",rt[k]);
    	else
    	{
    		int s=(k-be)%lo;
    		printf("%d
    ",rt[s+be]);
    	}
    	return 0;
    }
    

    (E.)

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

    组合数学,不会。

    先上结论:

    [ans=sumlimits_{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(klog 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
    ",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
    ");
    	else printf("Yes
    ");
    	return 0;
    }
    

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

  • 相关阅读:
    IE block my cookie in iframe
    error app/styles/components/iconfont.scss (Line 12: Invalid GBK character "xE5")
    angular4开发过程中遇到的问题和知识点记录
    博客
    009android初级篇之APP中使用系统相机相册等集成应用
    012android初级篇之Handler机制
    android studio win7开发环境
    001windows已遇到一个关键性问题 一分钟后自动重启
    008android初级篇之jni中数组的传递
    006android初级篇之jni数据类型映射
  • 原文地址:https://www.cnblogs.com/tlx-blog/p/12867954.html
Copyright © 2011-2022 走看看