zoukankan      html  css  js  c++  java
  • 2016"百度之星"

    题目比较基础。

    A题:

    算字符串连续子串的hash,线段树维护hash,这里并不是标准的hash,所以没难度。

    当然用前缀和+逆元好像也可以,不过我没想清楚如果被除数为0怎么处理逆元。

    #pragma comment(linker, "/STACK:102400000,102400000")
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #define REP(i,a,b) for(int i=a;i<=b;i++)
    #define MS0(a) memset(a,0,sizeof(a))
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    
    using namespace std;
    
    typedef long long ll;
    const int maxn=1000100;
    const int INF=1e9+10;
    
    const ll MOD=9973;
    ll H[maxn<<2];
    int n;
    char s[maxn];int len;
    int L,R;
    
    void push_up(int rt)
    {
        H[rt]=(H[rt<<1]*H[rt<<1|1])%MOD;
    }
    
    void build(int l,int r,int rt)
    {
        if(l==r){
            H[rt]=(s[l]+MOD-28)%MOD;
            return;
        }
        int m=(l+r)>>1;
        build(lson);
        build(rson);
        push_up(rt);
    }
    
    ll query(int L,int R,int l,int r,int rt)
    {
        if(L>R) return 0;
        //cout<<"L="<<L<<" R="<<R<<" l="<<l<<" r="<<r<<" rt="<<rt<<" Hrt="<<H[rt]<<endl;
        if(L<=l&&r<=R) return H[rt];
        int m=(l+r)>>1;
        ll res=1;
        if(L<=m) res=(res*query(L,R,lson))%MOD;
        if(R>m) res=(res*query(L,R,rson))%MOD;
        return res;
    }
    
    int main()
    {
        //freopen("in.txt","r",stdin);
        while(~scanf("%d",&n)){
            scanf("%s",s+1);
            len=strlen(s+1);
            build(1,len,1);
            while(n--){
                scanf("%d%d",&L,&R);
                printf("%I64d
    ",query(L,R,1,len,1));
            }
        }
        return 0;
    }
    View Code

    B题:

    设前i个的方案数为f[i],那么第i个要么和前一个合并,方案数为f[i-2],要么不合并,方案数为f[i-1],所以f[i]=f[i-1]+f[i-2]。

    由于斐波那契数列是指数级的,所以第200个肯定爆了longlong,需要模拟大数加法,或者直接用java。

    #pragma comment(linker, "/STACK:102400000,102400000")
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #define REP(i,a,b) for(int i=a;i<=b;i++)
    #define MS0(a) memset(a,0,sizeof(a))
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    
    using namespace std;
    
    typedef unsigned long long ll;
    const int maxn=1000100;
    const int INF=1e9+10;
    
    int n;
    string s[210];
    
    string add(string a,string b)
    {
        string c="";
        int la=a.size(),lb=b.size();
        int tag=0;
        if(la>lb) swap(la,lb),swap(a,b);
        //cout<<"a="<<a<<" b="<<b<<endl;
        REP(i,0,la-1){
            int t=a[i]-'0'+b[i]-'0'+tag;
            c+=(char)(t%10+'0');
            tag=t/10;
        }
        REP(i,la,lb-1){
            int t=b[i]-'0'+tag;
            c+=(char)(t%10+'0');
            tag=t/10;
        }
        if(tag) c+=(char)(tag+'0');
        //cout<<"c="<<c<<endl;
        return c;
    }
    
    void Init()
    {
        s[0]=s[1]="1";
        REP(i,2,201) s[i]=add(s[i-1],s[i-2]);
    }
    
    int main()
    {
        //freopen("in.txt","r",stdin);
        Init();
        while(~scanf("%d",&n)){
            if(n<=0) puts("");
            else{
                for(int i=s[n].size()-1;i>=0;i--) printf("%c",s[n][i]);puts("");
            }
        }
        return 0;
    }
    View Code

    C题:

    很基础的trie,直接维护个数sz,模拟插入删除就可以了,每次修改经过路径的值,删除结点的时候不用内存池回收,空间是够用的。

    #pragma comment(linker, "/STACK:102400000,102400000")
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #define REP(i,a,b) for(int i=a;i<=b;i++)
    #define MS0(a) memset(a,0,sizeof(a))
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    
    using namespace std;
    
    typedef unsigned long long ll;
    const int maxn=3000100;
    const int INF=1e9+10;
    
    struct Trie
    {
        int ch[maxn][26];
        int rt,tot;
        int sz[maxn];
        int newnode()
        {
            ++tot;
            MS0(ch[tot]);
            sz[tot]=0;
            return tot;
        }
        void init()
        {
            tot=0;
            rt=newnode();
        }
        void insert(char *s)
        {
            int len=strlen(s);
            int u=rt;
            REP(i,0,len-1){
                int c=s[i]-'a';
                if(!ch[u][c]) ch[u][c]=newnode();
                sz[ch[u][c]]++;
                u=ch[u][c];
            }
        }
        void del(char *s)
        {
            int len=strlen(s);
            int u=rt;
            REP(i,0,len-1){
                int c=s[i]-'a';
                if(!ch[u][c]) return;
                u=ch[u][c];
            }
            int t=sz[u];
            u=rt;
            REP(i,0,len-1){
                int c=s[i]-'a';
                u=ch[u][c];
                sz[u]-=t;
            }
            REP(c,0,25) ch[u][c]=0;
        }
        bool find(char *s)
        {
            int len=strlen(s);
            int u=rt;
            REP(i,0,len-1){
                int c=s[i]-'a';
                if(!ch[u][c]) return 0;
                u=ch[u][c];
            }
            return sz[u]!=0;
        }
    };Trie tr;
    int n;
    char op[maxn],s[maxn];
    
    int main()
    {
        while(cin>>n){
            tr.init();
            REP(i,1,n){
                scanf("%s%s",op,s);
                if(op[0]=='i') tr.insert(s);
                else if(op[0]=='d') tr.del(s);
                else puts(tr.find(s)?"Yes":"No");
            }
        }
        return 0;
    }
    View Code

    D题:

    map记录一下出现次数就可以了。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<string>
    #include<map>
    #define REP(i,a,b) for(int i=a;i<=b;i++)
    #define MS0(a) memset(a,0,sizeof(a))
    
    using namespace std;
    
    typedef long long ll;
    const int maxn=1000100;
    const int INF=1e9+10;
    
    int n;
    string s;
    map<string,int> cnt;
    
    int main()
    {
        while(cin>>n){
            cnt.clear();
            REP(i,1,n){
                cin>>s;
                sort(s.begin(),s.end());
                printf("%d
    ",cnt[s]);
                cnt[s]++;
            }
        }
        return 0;
    }
    View Code

    E题:

    由于变量只有30个,所以将每个条件每个变量的解集初始化为[-INF,INF],然后读入条件,和前面的暴力判断一下交集就可以了。

    主要是读入的过程,算是不太麻烦的小模拟。

    #pragma comment(linker, "/STACK:102400000,102400000")
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<vector>
    #include<map>
    #include<string>
    #define REP(i,a,b) for(int i=a;i<=b;i++)
    #define MS0(a) memset(a,0,sizeof(a))
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    
    using namespace std;
    
    typedef unsigned long long ll;
    const int maxn=3000100;
    const int INF=1e9+10;
    
    int cn;
    struct Node
    {
        int L[40],R[40];
        bool kong;
    };Node a[maxn];
    map<string,int> id;
    int n;
    char s[maxn];
    
    int main()
    {
        freopen("in.txt","r",stdin);
        while(cin>>n){
            id.clear();
            REP(i,1,n) REP(j,1,30) a[i].L[j]=-INF,a[i].R[j]=INF,a[i].kong=0;
            cn=0;
            gets(s);
            //cout<<"s="<<s<<endl;
            REP(i,1,n){
                gets(s);
                int len=strlen(s);
                //cout<<"s="<<s<<endl;
                for(int j=0;j<len;){
                    while(j<len&&s[j]==' ') j++;
                    string name="";
                    while(j<len&&s[j]!=' ') name+=s[j++];
                    while(j<len&&s[j]==' ') j++;
                    string p="";
                    while(j<len&&s[j]!=' ') p+=s[j++];
                    while(j<len&&s[j]==' ') j++;
                    int num=0;
                    int ttt=1;
                    if(s[j]=='-') ttt=-1,j++;
                    while(j<len&&s[j]!=' ') num=num*10+s[j]-'0',j++;
                    while(j<len&&s[j]==' ') j++;
                    while(j<len&&s[j]==',') j++;
                    num*=ttt;
                    if(!id[name]) id[name]=++cn;
                    int x=id[name];
                    if(p=="<") a[i].R[x]=min(a[i].R[x],num-1);
                    else if(p=="<=") a[i].R[x]=min(a[i].R[x],num);
                    else if(p==">") a[i].L[x]=max(a[i].L[x],num+1);
                    else if(p==">=") a[i].L[x]=max(a[i].L[x],num);
                    else if(p=="==") a[i].L[x]=max(a[i].L[x],num),a[i].R[x]=min(a[i].R[x],num);
                    //cout<<"j="<<j<<" len="<<len<<endl;
                }
                REP(j,1,30) if(a[i].L[j]>a[i].R[j]) a[i].kong=1;
                vector<int> ans;
                REP(j,1,i-1){
                    if(a[j].kong||a[i].kong) continue;
                    bool has=1;
                    REP(k,1,30){
                        if(a[i].L[k]>a[j].R[k]||a[j].L[k]>a[i].R[k]){
                            has=0;break;
                        }
                    }
                    if(has) ans.push_back(j);
                }
                if(a[i].kong||(int)ans.size()==0) puts("unique");
                else{
                    for(int j=0;j<ans.size();j++){
                        printf("%d",ans[j]);
                        if(j!=(int)ans.size()-1) printf(" ");
                        else printf("
    ");
                    }
                }
            }
            //REP(i,1,cn) cout<<a[3].L[i]<<" "<<a[3].R[i]<<" "<<a[3].kong<<endl;
        }
        return 0;
    }
    View Code
    没有AC不了的题,只有不努力的ACMER!
  • 相关阅读:
    【阿里云产品评测】装甲兵在云路上!
    区间交集问题
    信封嵌套问题
    twoSum问题的核心思想
    队列实现栈|栈实现队列
    设计Twitter 时间线
    如何使用单调栈解题
    二叉堆详解实现优先级队列
    git/SQL/正则表达式的在线练习网站
    我的 Redis 被入侵了
  • 原文地址:https://www.cnblogs.com/--560/p/5498834.html
Copyright © 2011-2022 走看看