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

  • 相关阅读:
    《疯狂的程序员》二
    《当程序员的那些狗日日子》五
    《疯狂的程序员》九
    《疯狂的程序员》一
    《疯狂的程序员》三
    和菜鸟一起学算法之递归和分治简单实例
    《疯狂的程序员》八
    《当程序员的那些狗日日子》四
    开放源代码软件利润高于专有代码
    少年黑客破解Google视频播放器
  • 原文地址:https://www.cnblogs.com/Chen-Jr/p/11007141.html
Copyright © 2011-2022 走看看