• Technocup 2020


    慢慢来。

    题目册

    题目 A B C D
    tag math strings greedy dp
    状态
    //∅,√,×

    想法

    A. CME

    res tp A
    题意:有(n)根火柴,额外填上(k(k≥0))根火柴棍,使得(n+k)能分成三份(a,b,c),每份至少有一根火柴,满足(a+b = c),问(k)最小是多少
    满足方程
    (a+b+c = n+k)
    (a + b = c)
    (2*c = n+k)
    (n)是偶数,那么(k)为零,反之(k)(1)
    特别地,(n)至少要为(4),才能凑出一个等式(1+1=2)

    #include<bits/stdc++.h>
    #define rep(i,a,b) for(int i=(a);i<=(b);++i)
    #define per(i,a,b) for(int i = (a);i>=(b);--i)
    #define fo(i,a,b) for(int i =(a);i<(b);++i)
    #define de(x) cout<<#x<<" = "<<x<<endl;
    #define endl '
    '
    #define mem(a,b) memset(a,b,sizeof(a));
    #define ls(p) ((p)<<1)
    #define rs(p) (((p)<<1)|1)
    using namespace std;
    typedef long long ll;
    const int mn = 105;
    
    int n,q;
    int main(){
    	cin>>q;
    	while(q--){
    		cin>>n;
    		if(n < 4)
    			cout<<4 - n<<endl;
    		else
    			cout<< (n&1) <<endl;
    	}
    }
    

    B. Strings Equalization

    res tp B
    题意:给出两个仅包含小写字母的字符串,问是否存在某个字符在两串中都出现过

    #include<bits/stdc++.h>
    #define rep(i,a,b) for(int i=(a);i<=(b);++i)
    #define per(i,a,b) for(int i = (a);i>=(b);--i)
    #define fo(i,a,b) for(int i =(a);i<(b);++i)
    #define de(x) cout<<#x<<" = "<<x<<endl;
    #define endl '
    '
    #define mem(a,b) memset(a,b,sizeof(a));
    #define ls(p) ((p)<<1)
    #define rs(p) (((p)<<1)|1)
    using namespace std;
    typedef long long ll;
    const int mn = 105;
    
    
    char s[mn],t[mn];
    int q,m;
    bool vis[27],ans;
    int main(){
    	cin>>q;
    	while(q--){
    		cin>>s>>t;
    		ans = 0;
    		mem(vis,0);
    		m =strlen(s);
    		rep(i,0,m-1)	vis[ s[i]-'a' ] = 1;
    		rep(i,0,m-1) if(vis[t[i]-'a']){
    			ans = 1;break;
    		}
    		if(ans) cout<<"YES"<<endl;
    		else cout<<"NO"<<endl;
    	}
    }
    
    
    

    C. Save the Nature

    res tp C
    题意:给定一个整数序列(p_i,iin[1,n]),你可以对其进行打乱顺序重新排列。定义了一个规则,下标是(a)的倍数的,可以有(x%)的贡献,下标是(b)的倍数的,可以有(y%)的贡献,问,在重排之后,按上述规则,从(1)开始,最少需要多少个连续的数,使得总贡献不小于(k)
    贪心地考虑,下标若既是(a)的倍数,又是(b)的倍数,那岂不是能贡献两份吗?我们先按从大到小的顺序钦定这类下标的元素值,之后再依照(x)(y)的大小关系继续钦定剩下的对答案有贡献的位置,遍历区间([1,i]),执行上述操作,直到遇到第一个总贡献不小于(k)的下标,而那就是我们想要得到的最终答案。

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<queue>
    #define rep(i,a,b) for(int i=(a);i<=(b);++i)
    #define per(i,a,b) for(int i = (a);i>=(b);--i)
    #define fo(i,a,b) for(int i =(a);i<(b);++i)
    #define de(x) cout<<#x<<" = "<<x<<endl;
    #define endl '
    '
    #define ls(p) ((p)<<1)
    #define rs(p) (((p)<<1)|1)
    using namespace std;
    typedef long long ll;
    const int mn = 2e5+10;
    int n, q, na, nb, nc, x, y, a, b;
    ll p[mn], k;
    bool cmp1(ll a,ll b){return a>b;}
    int ans;
    inline ll gcd(ll x,ll y){
    	return (y == 0? x:gcd(y,x%y));
    }
    inline ll solve(int num){
    	na = num/a;nb = num/b;
    	nc = na&&nb?num/(a/gcd(a,b)*b):0; nb-=nc;na-=nc;
    	ll res = 0;
    	res += (p[nc] - p[0])*(x+y);
    	if(x > y){
    		res += (p[nc + na]- p[nc])*x;
    		res += (p[nc + na + nb] - p[nc + na])*y;
    	}
    	else{
    		res += (p[nc + nb] - p[nc])*y;
    		res += (p[nc + na + nb] - p[nc + nb])*x;
    	}
    	return res/100;
    }
    
    int main(){
    	scanf("%d",&q);
    	while(q--){
    		scanf("%d",&n);
    		rep(i,1,n) cin>>p[i];
    		sort(p+1,p+1+n,cmp1);
    		rep(i,1,n) p[i] += p[i-1];
    		scanf("%d%d%d%d",&x,&a,&y,&b);
    		scanf("%lld",&k);
    		ans = -1;
    		rep(i,1,n)	if( solve(i) >=k ){
    			ans = i;
    			break;
    		}
    		printf("%d
    ",ans);
    	}
    }
    

    D. Sequence Sorting

    res tp D
    题意:给定一个序列,可以进行进行一种操作:选定一个x,之后将值为x的所有数字移动到序列的最左端或最右端,问最少进行多少次操作,使得序列满足单调不减

    首先取出原序列中我们需要的信息,而其他的信息可以忽略。求出其每种元素的两个特征:初次出现位置和末次出现位置。
    按元素值从小到大的序列就是我们最终要得到的序列。为了让操作数尽可能小,我们需要省去一些力气。如果原序列和终序列在某些地方是“相似”的,岂不是可以省去对这部分“相似”的操作吗?
    具体地说,对终序列的两个数值紧邻的元素,若他们的分布区间不相交,且保证较小的元素的区间在较大的元素的左侧,那么这两种元素的相对位置在两个序列中是相等的,也就是说,它们对操作数没有贡献。
    反之,至少要对其中的一个元素进行操作,同时,这也意味着,被操作元素那一侧的所有元素都要被操作。
    综上,不需要操作的元素一定在终序列中是连续,于是可以dp出终序列满足条件的最长子区间,再用元素种类数减之即为答案

    #include<bits/stdc++.h>
    #define rep(i,a,b) for(int i=(a);i<=(b);++i)
    #define per(i,a,b) for(int i = (a);i>=(b);--i)
    #define fo(i,a,b) for(int i =(a);i<(b);++i)
    #define de(x) cout<<#x<<" = "<<x<<endl;
    #define endl '
    '
    #define mem(a,b) memset(a,b,sizeof(a));
    #define ls(p) ((p)<<1)
    #define rs(p) (((p)<<1)|1)
    using namespace std;
    typedef long long ll;
    const int mn = 3e5+10;
    int q,n;
    struct E{
        int v,l,r;
    }e[mn];
    int vis[mn],t,cnt,mdp,dp;
    bool cmp(E a,E b){return a.v <b.v;}
    int main(){
    	scanf("%d",&q);
    	while(q--){
    		cnt = 1;
    		scanf("%d",&n);
    		rep(i,1,n){
    			scanf("%d",&t);
    			if(vis[t])
    				e[vis[t]].r	= i;
    			else{
    				e[cnt].l = e[cnt].r = i;
    				e[cnt].v = t;
    				vis[t] = cnt++;
    			}
    		}
    		sort(e+1,e+cnt,cmp);
    		mdp = dp = 1;
    		int cnt1 = cnt - 1;
    		rep(i,2,cnt1){
    			if(e[i-1].r <e[i].l) ++dp;
    			else dp = 1;
    			mdp = max(mdp,dp);
    		}
    		printf("%d
    ",cnt - 1 - mdp);
    		rep(i,1,cnt1) vis[e[i].v] = 0;
    	}
    }
    

  • 相关阅读:
    linux软件包安装yum
    linux软件包安装rpm
    使用OwnCloud建立属于自己私有的云存储网盘
    Linux 防火墙
    Linux docker
    llinux 权限2
    详列JDK中的设计模式(二)结构型
    详列JDK中的设计模式(一)创建型
    JavaWeb学习总结(一) JavaWeb基础与Tomcat服务器
    老生常谈-从输入url到页面展示到底发生了什么
  • 原文地址:https://www.cnblogs.com/tea-egg/p/11644875.html
Copyright © 2020-2023  润新知