zoukankan      html  css  js  c++  java
  • Gym102174 (The 14-th BIT Campus Programming Contest)

    传送门:

    Problem A

    温暖的签到题,用个map记录一下就行了。

    #include <bits/stdc++.h>
    using namespace std;
    string str[20];
    map<string,int>mp;
    int main()
    {
        //sfreopen("in.txt","r",stdin);
        //1 chui 0 xi
        mp["5--"]=1;
        mp["2-"]=0;
        mp["1-"]=1;
        mp["4-"]=0;
        mp["3-"]=1;
        mp["6-"]=0;
        mp["5-"]=1;
        mp["7-"]=0;
        mp["1"]=1;
        mp["2"]=0;
        mp["3"]=1;
        mp["4"]=0;
        mp["5"]=1;
        mp["6"]=0;
        mp["1+"]=1;
        mp["7"]=0;
        mp["3+"]=1;
        mp["2+"]=0;
        mp["5+"]=1;
        mp["4+"]=0;
        mp["1++"]=1;
        mp["6+"]=0;
        mp["3++"]=1;
        mp["7+"]=0;
        mp["0"]=-1;
        int n;
        cin>>n;
        for(int i=1;i<=n;i++){
            string str;
            cin>>str;
            if(mp[str]==-1) printf("X");
            else if(mp[str]==1) printf("E");
            else printf("I");
        }
        return 0;
    }
    

    Problem B

    题意:

    给你mm个串,现在让你构建一个长度为nnstrstr串,使得这mm个串的都不是strstr的子串。

    分析:

    考虑AC自动机。

    将所给的mm个串建立AC自动机,之后我们可以考虑的一个算法是,对现在所形成的Tire图进行dfs遍历,倘若发现我们能够在这张Trie图上走nn步,则我们就将这nn步的结果输出即可。

    但是因为在这里,状态数达到了26m26^m之多,如果之间对Tire图进行遍历必然会超时,故现在考虑优化。

    我们发现在我们形成的Trie图中,显然是存在大量的有效环,即存在不经过EndEnd结点的环,而倘若遇到一个这样的环,则我们只需要直接不断经过这个环即可。如此我们就可以避免遍历大量的无效的状态。

    因此我们只需要预先进行预处理,我们首先先对Trie图进行遍历,记录一下有哪些结点是能够形成环,最后我们只需要在统计答案的时候优先通过这些的结点即可。

    代码:
    #include <bits/stdc++.h>
    #define maxn 500005
    using namespace std;
    char str[maxn];
    int n,m;
    struct Trie{
        int next[maxn][26],End[maxn],root,fail[maxn],id;
        int vis[maxn],num[maxn],ans[maxn];
        int newnode(){
            for(int i=0;i<26;i++){
                next[id][i]=-1;
            }
            End[id]=0,vis[id]=0,num[id]=0;
            return id++;
        }
        void init(){
            id=0;
            root=newnode();
        }
        void Insert(char *str){
            int len=strlen(str);
            int now=root;
            for(int i=0;i<len;i++){
                if(next[now][str[i]-'a']==-1)
                    next[now][str[i]-'a']=newnode();
                now=next[now][str[i]-'a'];
            }
            End[now]++;
        }
        void build(){
            queue<int>que;
            int now=root;
            fail[root]=root;
            for(int i=0;i<26;i++){
                if(next[root][i]==-1){
                    next[root][i]=root;
                }
                else{
                    fail[next[root][i]]=root;
                    que.push(next[root][i]);
                }
            }
            while(!que.empty()){
                now=que.front();
                que.pop();
                End[now]|=End[fail[now]];
                for(int i=0;i<26;i++){
                    if(next[now][i]==-1)
                        next[now][i]=next[fail[now]][i];
                    else{
                        fail[next[now][i]]=next[fail[now]][i];
                        que.push(next[now][i]);
                    }
                }
            }
        }
        void dfs1(int now){//预处理
            vis[now]=1;
            for(int i=0;i<26;i++){
                if(vis[next[now][i]]==0&&next[now][i]!=root){
                    if(End[next[now][i]]) continue;
                    dfs1(next[now][i]);
                    num[now]|=num[next[now][i]];
                }
                else num[now]=1;
            }
        }
        int dfs2(int step,int now,int fa){
            if(fa!=-1) ans[step]=fa;
            if(step==n) return 1;
            for(int i=0;i<26;i++){
                if((!End[next[now][i]]||next[now][i]==root)&&num[next[now][i]]!=0){
                    if(dfs2(step+1,next[now][i],i)) return 1;
                }
            }
            return 0;
        }
    }ac;
    int main()
    {
        //freopen("in.txt","r",stdin);
        scanf("%d%d",&n,&m);
        ac.init();
        for(int i=0;i<m;i++){
            scanf("%s",str);
            ac.Insert(str);
        }
        ac.build();
        ac.dfs1(0);
        ac.dfs2(0,ac.root,-1);
        for(int i=1;i<=n;i++){
            printf("%c",ac.ans[i]+'a');
        }
        return 0;
    }
    
    

    Problem C

    题意:

    nn个怪兽,第ii个怪兽的血量为did_i,攻击力为aia_i,你的攻击力为kk,你现在有cc个力量果实,每吃一个力量果实都可以让你攻击力增加kk,问你最少扣多少血。

    分析:

    考虑贪心,显然的贪心策略是优先嗑药秒掉那些攻击力大且血比较厚的怪物。

    代码:
    #include <bits/stdc++.h>
    #define maxn 100005
    using namespace std;
    typedef long long ll;
    int n,k,c;
    struct Node{
        ll d1,x1;
        bool operator <(const Node&b)const{
            return x1>b.x1;
        }
    }q[maxn];
    int main()
    {
        scanf("%d%d%d",&n,&k,&c);
        for(int i=1;i<=n;i++){
            scanf("%lld%lld",&q[i].d1,&q[i].x1);
            q[i].d1=(q[i].d1+k-1)/k-1;
        }
        sort(q+1,q+1+n);
        ll res=0;
        for(int i=1;i<=n;i++){
            if(q[i].d1<=c){
                c-=q[i].d1;
                continue;
            }
            else{
                res+=(q[i].d1-c)*q[i].x1;
                c=0;
            }
        }
        printf("%lld
    ",res);
        return 0;
    }
    

    Problem D


    Problem E

    题意:

    有一个大小为nn个排列,现在你你有若干个栈以及3中操作:

    1. 取出序列当前的第一个数字,插入到第 pp 个栈的顶部
    2. 取出第 pp 个栈的顶部数字,插入到新序列的末尾位置
    3. 取出第 pp 个栈的顶部数字,插入到第 qq 个栈的顶部

    问你最少花费多少个栈使得原排列变成升序。

    分析:

    不难看出可以我们最多用22个栈就可以完成上述操作。

    而当且仅当形成ai1 ai2 a1 anai2a_{i-1}~a_{i-2}dots~a_1~a_{n}dots a_{i-2}这样的序列才能用11个栈完成。

    而上述的过程,我们只需要用一个单调栈去维护即可。

    代码:
    #include <bits/stdc++.h>
    #define maxn 100005
    using namespace std;
    int a[maxn];
    int main()
    {
        //freopen("in.txt","r",stdin);
        int t;
        scanf("%d",&t);
        while(t--){
            int n;
            scanf("%d",&n);
            for(int i=1;i<=n;i++){
                scanf("%d",&a[i]);
            }
            stack<int>st;
            while(!st.empty()) st.pop();
            int minn=1;
            bool vis=true;
            for(int i=1;i<=n;i++){
                if(st.empty()){
                    st.push(a[i]);
                    continue;
                }
                while(!st.empty()&&st.top()<a[i]){
                    if(st.top()!=minn){
                        vis=false;
                        break;
                    }
                    minn++,st.pop();
                }
                if(!vis) break;
                st.push(a[i]);
            }
            while(!st.empty()){
                if(!vis) break;
                if(st.top()!=minn){
                    vis=false;
                    break;
                }
                minn++,st.pop();
            }
            if(!vis) puts("2");
            else puts("1");
        }
        return 0;
    }
    

    Problem F

    温暖的签到题,找一下规律就没了

    代码:
    #include <bits/stdc++.h>
    #define maxn 100005
    using namespace std;
    typedef long long ll;
    ll n,m;
    int main()
    {
        ios::sync_with_stdio(false);
        cin.tie(0);
        int t;
        cin>>t;
        while (t--){
            cin>>n>>m;
            ll ans=0;
            for (int i=1;i<=min(n,m);i++)
                ans+=(n-i+1)*(m-i+1)*i;
            cout<<ans<<endl;
        }
        return 0;
    }
    

    Problem G


    Problem H

    解一下方程,最后注意可能会产生增根,特判一下即可。

    代码:
    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    vector<ll>ans;
    ll a,b;
    bool check(ll x){
        ll tmp=a*x;
        if (tmp<0) return 0;
        ll c=sqrt(tmp);
        if (c*c!=tmp) return 0;
        if (c+b==x) return 1;
        return 0;
    }
    int main(){
        ios::sync_with_stdio(false);
        cin.tie(0);
        int t;
        cin>>t;
        while (t--){
            cin>>a>>b;
            ll tmp=a*a+4*a*b;
            ll c=sqrt(tmp);
            if (c*c==tmp) {
                ll x1=a+2*b-c;
                ll x2=a+2*b+c;
                ans.clear();
                if (x1%2==0&&x1!=x2){
                    x1/=2;
                    if (check(x1)) ans.push_back(x1);
                }
                if (x2%2==0){
                    x2/=2;
                    if (check(x2)) ans.push_back(x2);
                }
                sort(ans.begin(),ans.end());
                cout<<ans.size()<<endl;
                cout<<ans[0];
                for (int i=1;i<ans.size();i++) cout<<' '<<ans[i];
                cout<<endl;
            }
        }
        return 0;
    }
    

    Problem I


    Problem J


    Problem K

    签到题,模拟一下求导过程即可

    代码:
    #include <bits/stdc++.h>
    using namespace std;
    
    int n,k;
    const int mod=998244353;
    typedef long long ll;
    ll a[105];
    ll Ans(ll x){
        ll res=1;
        for(int i=x,j=1;i>=1&&j<=k;i--,j++){
            res=res*i%mod;
        }
        return res;
    }
    vector<ll>res;
    int main()
    {
        scanf("%d%d",&n,&k);
        for(int i=1;i<=k;i++) res.push_back(0);
        for(int i=n;i>=1;i--){
            scanf("%lld",&a[i]);
            if(i<k) continue;
            else res.push_back((Ans(i)*a[i])%mod);
        }
        for(int i=0;i<res.size();i++){
            if(i==0) printf("%lld",res[i]);
            else printf(" %lld",res[i]);
        }
        return 0;
    }
    

    Problem L


    Problem M

  • 相关阅读:
    HDU 1022 Train Problem I
    HDU 1702 ACboy needs your help again!
    HDU 1294 Rooted Trees Problem
    HDU 1027 Ignatius and the Princess II
    HDU 3398 String
    HDU 1709 The Balance
    HDU 2152 Fruit
    HDU 1398 Square Coins
    HDU 3571 N-dimensional Sphere
    HDU 2451 Simple Addition Expression
  • 原文地址:https://www.cnblogs.com/Chen-Jr/p/11007141.html
Copyright © 2011-2022 走看看