• 【AtCoder】ABC 167


    AtCoder Beginner Contest 167

    A Registration

    给两个字符串,长度为 \(n\)\(n+1\)。检查第二个字符串的前 \(n\) 位是不是第一个字符串。枚举一下每一位即可。

    #include<bits/stdc++.h>
    using namespace std;
    string s,t;
    int main(){
    	cin>>s>>t;
    	bool ans=1;
    	for(int i=0;i<s.size();i++) if(s[i]!=t[i]) ans=0;
    	cout<<(ans?"Yes":"No");
    	return 0;
    } 
    

    B Easy Linear Programming

    对于选出的 \(k\) 张卡片,肯定优先选择 \(1\) 的,再选 \(0\) 的,最后是 \(-1\) 的。于是我们分类讨论即可,

    #include<bits/stdc++.h>
    using namespace std;
    int n,m,x,y,z,ans;
    int main(){
    	cin>>x>>y>>z>>n;
    	if(x>=n) ans=n;
    	else if(x+y>=n) ans=x;
    	else ans=x-(n-x-y);
    	cout<<ans;
    	return 0;
    } 
    

    C Skill Up

    暴力枚举每一本书选不选,然后判断是否合法最后更新答案即可,

    #include<bits/stdc++.h>
    using namespace std;
    const int N=109;
    int n,m,x,c[N],a[N][N],p[N],ans=0x3f3f3f3f;
    void dfs(int s,int price){
    	if(s==n+1){
    		for(int i=1;i<=m;i++) if(p[i]<x) return;
    		ans=min(ans,price); 
    		return;
    	}
    	dfs(s+1,price);
    	for(int i=1;i<=m;i++) p[i]+=a[s][i];
    	dfs(s+1,price+c[s]);
    	for(int i=1;i<=m;i++) p[i]-=a[s][i];
    }
    int main(){
    	cin>>n>>m>>x;
    	for(int i=1;i<=n;i++){
    		cin>>c[i];
    		for(int j=1;j<=m;j++) cin>>a[i][j];
    	}
    	dfs(1,0);
    	if(ans>1e9) cout<<-1;
    	else cout<<ans;
    	return 0;
    }
    

    D Teleporter

    用dfs处理出环,然后分类讨论,国王有没有走到环上。由于走到换上就不会出来了,直接取模即可。

    #include<bits/stdc++.h>
    #define int long long
    using namespace std;
    const int N=2e5+9;
    int n,k; bool vst[N],in[N]; int tot,sl,a[N],cnt,loop[N];
    void dfs(int u){
    	tot++; vst[u]=1; int v=a[u];
    	if(vst[v]) sl=v;
    	else dfs(v);
    }
    signed main(){
    	scanf("%lld%lld",&n,&k);
    	for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
    	dfs(1); int u=sl; int find=0;
    	while(1){
    		if(u==sl&&find) break;
    		find=1, loop[++cnt]=u, in[u]=1;
    		u=a[u];
    	} loop[0]=loop[cnt];
    	if(k<=tot-cnt){
    		int ans=1;
    		for(int i=1;i<=k;i++) ans=a[ans];
    		cout<<ans;
    	}else{
    		k++;
    		cout<<loop[(k-(tot-cnt))%cnt];
    	}
    	return 0;
    

    E Colorful Blocks

    看到题立马想到一个 \(O(nk)\)\(dp\)…… 可惜这题是个组合题。

    没关系,有 \(dp\) 可以找规律观察。\(f(i,j)\) 表示前 \(i\) 个格子有 \(j\) 对相等的。

    \[f(i,j)=f(i-1,j-1)+f(i-1,j)\times (m-1) \]

    然后经过一系列的推导(我不会)和列式子观察(这个才是),我们发现每一个 \(f(i,j)\) 都是一个可以化作乘积的形式,常数项是 \(C_{i-1}^{j}\),且都含有 \(m\)\(m-1\),其中 \(m\) 的指数是 \(1\)\(m-1\) 的指数是一个连续递减数列,为 \(i-j-1\)。于是我们可以搞得式子:

    \[f(i,j)=C_{i-1}^j\times m\times (m-1)^{i-j-1} \]

    这个故事告诉我们:手动打表和多项式很重要

    最后求出 \(\sum f(n,j)\) 即可。

    #include<bits/stdc++.h>
    #define int long long
    using namespace std;
    const int N=1e6+9,mod=998244353;
    int n,m,k,ans,fact[N],inv[N];
    int qp(int a,int b=mod-2){
        return (b==0?1:(b%2?qp(a*a%mod,b/2)*a%mod:qp(a*a%mod,b/2)));
    }
    int C(int a,int b){return fact[a]*inv[b]%mod*inv[a-b]%mod;}
    signed main(){
    	scanf("%lld%lld%lld",&n,&m,&k);
    	for(int i=0;i<=n;i++) fact[i]=(i==0?1:fact[i-1]*i%mod);
    	for(int i=n;i>=0;i--) inv[i]=(i==n?qp(fact[n]):inv[i+1]*(i+1)%mod);
    	for(int j=0;j<=k;j++){
    		ans=(ans+m*C(n-1,j)%mod*qp(m-1,n-j-1))%mod;
    	}
    	printf("%lld",ans);
    	return 0;
    } 
    

    F Bracket Sequencing

    这题其实需要一个构造。按照想好的构造方案去弄,如果可行,那么就是Yes,否则就是No。

    这题和这题有很大的相似之处。我们可以把左括号理解成回血,右括号理解为掉血。

    这个字符串的前缀和(左括号为+1,右括号为-1)的最小值即可以理解为最大的耗血,最大值可以理解为最大的回血。

    对于一个字符串,如果它的总和是非负的,我们肯定先打最小值最大的(即最小耗血)。

    对于一个字符串,如果它的总和是负的,按照比赛讨论区的题解的说法,他们是对称的;按照上面那题的题解来说,我们可以反过来看,即右括号变成+1,左括号-1,那么显然应该从右往左选前缀最大值最小的,即从左往右看,后缀最大值最大的。

    所以最后再统计一下即可。

    int n,ac,bc;
    struct str{int m;string st;}a[N],b[N];
    bool cmp(const str&a,const str&b){return a.m>b.m;}
    string last="";
    int main(){
    	cin>>n;
    	for(int i=1;i<=n;i++){
    		string s; cin>>s;
    		int sum=0,mx=-1e9,mn=1e9;
    		for(int j=0;j<s.size();j++){
    			if(s[j]=='(') sum++;
    			else sum--;
    			mn=min(mn,sum);
    		} sum=0;
    		for(int j=s.size()-1;j>=0;j--){
    			if(s[j]=='(') sum++;
    			else sum--;
    			mx=max(mx,sum);
    		}
    		if(sum>=0) a[++ac]=(str){mn,s};
    		else b[++bc]=(str){mx,s};
    	}
    	sort(a+1,a+ac+1,cmp), sort(b+1,b+bc+1,cmp);
    	for(int i=1;i<=ac;i++) last+=a[i].st;
    	for(int i=1;i<=bc;i++) last+=b[i].st;
    	int sum=0;
    	for(int i=0;i<last.size();i++){
    		if(last[i]=='(') sum++;
    		else sum--;
    		if(sum<0) return puts("No"),0;
    	}
    	if(sum==0) puts("Yes");
    	else puts("No");
    	return 0;
    }
    
  • 相关阅读:
    路飞学城Python-Day19
    路飞学城Python-Day18
    路飞学城Python-Day17
    ES6新特性概览
    关于Flex,有12个属性很重要
    Web前端工程师成长之路——知识汇总
    解决ajax跨域请求 (总结)
    项目中关于AJAX的使用总结
    Web前端性能优化——如何提高页面加载速度
    Canvas和SVG的区别
  • 原文地址:https://www.cnblogs.com/TetrisCandy/p/ABC167.html
Copyright © 2020-2023  润新知