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

  • 相关阅读:
    20155313 杨瀚 《网络对抗技术》实验九 Web安全基础
    20155313 杨瀚 《网络对抗技术》实验八 Web基础
    20155313 杨瀚 《网络对抗技术》实验七 网络欺诈防范
    20155313 杨瀚 《网络对抗技术》实验六 信息搜集与漏洞扫描
    20155313 杨瀚 《网络对抗技术》实验五 MSF基础应用
    20155313 杨瀚 《网络对抗技术》实验四 恶意代码分析
    20155313 杨瀚 《网络对抗技术》实验三 免杀原理与实践
    20155313 杨瀚 《网络对抗技术》实验二 后门原理与实践
    20155313 杨瀚 《网络对抗技术》实验一 PC平台逆向破解(5)M
    20155313 2017-2018-1 《信息安全系统设计基础》课程总结
  • 原文地址:https://www.cnblogs.com/Chen-Jr/p/11007141.html
Copyright © 2011-2022 走看看