2019 cattle and more passengers sixth school

A Garbage Classification

The meaning of problems

Given a string representing the garbage, 26 characters each character represents a certain composition, garbage categories to determine meaning of the questions.

analysis

Warm attendance problems, be careful not to write the division on the line.

Code

#include <bits/stdc++.h>
using namespace std;
const int N=2050;
int T;
char s[N];
char let[30];
map<char,char> mp;
int main(void){
//    freopen("in.txt","r",stdin);
    scanf("%d",&T);
    for(int cas=1;cas<=T;cas++){
        scanf("%s",s);
        scanf("%s",let);
        mp.clear();
        for(int i=0;i<26;i++){
            mp['a'+i]=let[i];
        }
        int d=0,w=0,h=0;
        int len=strlen(s);
        for(int i=0;i<len;i++){
            if(mp[s[i]]=='d'){
                d++;
            }else if(mp[s[i]]=='w'){
                w++;
            }else if(mp[s[i]]=='h'){
                h++;
            }
        }
        printf("Case #%d: ",cas);
        if(4*h>=len){
            printf("Harmful\n");
        }else if(10*h<=len){
            printf("Recyclable\n");
        }else{
            if(d>=2*w){
                printf("Dry\n");
            }else{
                printf("Wet\n");
            }
        }
    }
    return 0;
}

B Shorten IPv6 Address

The meaning of problems

Given a 128-bit binary number, first converted into 32-bit hexadecimal number, with each group of four, separated by a colon, and then if a group is 0, then with 4 1 0 0 replaced i.e. you can then be selected and only a string of continuous string of 0 and colon, replaced by two colons, Q can be obtained which is lexicographically smallest.

analysis

First constructed the original string, and then eight groups, the recording position in the string, and then make continuous 0 enumerate the beginning of each set of replacement strings obtained after a double colon, direct violence to find all the strings, sorting can be.

Code

#include <bits/stdc++.h>
using namespace std;
int T;
char s[130];
char hex(char a,char b,char c,char d){
    int t=(a-'0')*8+(b-'0')*4+(c-'0')*2+(d-'0');
    if(t<=9){
        return char(t+'0');
    }else{
        return char(t-10+'a');
    }
}
vector<string> vs;
bool cmp(string a,string b){
    int al=a.size();
    int bl=b.size();
    if(al==bl){
        return a<b;
    }else{
        return al<bl;
    }
}
int idx[8];
int main(void){
//    freopen("in.txt","r",stdin);
    scanf("%d",&T);
    for(int cas=1;cas<=T;cas++){
        scanf("%s",s);
        memset(idx,0,sizeof(idx));
        string he="";
        int cnt=0;
        for(int i=0;i<128;i+=16){
            string t="";
            bool ac=false;
            for(int j=i;j<i+16;j+=4){
                char p=hex(s[j],s[j+1],s[j+2],s[j+3]);
                if(!ac && p=='0'){
                    continue;
                }
                ac=true;
                t+=p;
            }
            int q=he.size();
            if(t==""){
                he+="0";
            }else{
                he+=t;
            }
            idx[cnt++]=q;
            if(i==112){
                continue;
            }
            he+=":";
        }
        vs.clear();
        vs.push_back(he);
        int hes=he.size();
        for(int i=0;i<8;i++){
            string tle="";
            int t=idx[i];
            if(i!=0){
                t--;
            }
            for(int j=0;j<t;j++){
                tle+=he[j];
            }
            int mle=0;
            while(t<hes && he[t]=='0' || he[t]==':'){
                if(he[t]=='0'){
                    mle++;
                }
                t++;
            }
            if(mle>=2){
                tle+="::";
            }else{
                int j=idx[i];
                if(i!=0){
                    j--;
                }
                for(;j<t;j++){
                    tle+=he[j];
                }
            }
            for(int j=t;j<hes;j++){
                tle+=he[j];
            }
            vs.push_back(tle);
        }
        sort(vs.begin(),vs.end(),cmp);
        printf("Case #%d: %s\n",cas,vs[0].c_str());
    }
    return 0;
}

C Palindrome Mouse

The meaning of problems

Given a string, the number of request \ ((a, b) \ ) satisfies \ (A \) and \ (B \) are palindromic substring of the original string, and \ (A \) is \ (B \ ) substrings.

analysis

  • First palindromic tree structure with all palindromic substring node, for each node, the contribution of the answer consists of two parts, a pointer portion is fail, the fail point such aa aaa, then the substring is aa aaa, and because all tree nodes, i.e. are palindromes, the other part is the next pointer, such as next point and bb abba, then the substring is abba bb, and can be seen to fail bb b pointer should also abba the substring.

  • So we need to find the number of times each node pointers fail to jump up and down next pointer jump, multiplication Theorem to calculate the contribution of each node.

  • The method of seeking the number of next dfs Qiuzi similar tree size, while at the same time seeking fail dfs violence pointer up, in order to avoid double counting, such as bb skipped fail pointer jump bbbb not need violence which each pointer flag node hops, after dfs violence also finished emptying markers.

Code

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+50;
int vis[N],ndp[N],fdp[N];
struct PT{
    int next[N][26],fail[N],cnt[N],num[N],len[N];
    int S[N],last,id[N],n,p;
    int newnode(int l){
        for(int i=0;i<26;i++){
            next[p][i]=0;
        }
        cnt[p]=num[p]=0;
        len[p]=l;
        return p++;
    }
    void init(){
        p=0;
        newnode(0);
        newnode(-1);
        last=0;
        n=0;
        S[n]=-1;
        fail[0]=1;
    }
    int getFail(int x){
        while(S[n-len[x]-1]!=S[n]){
            x=fail[x];
        }
        return x;
    }
    void add(int c){
        c-='a';
        S[++n]=c;
        int cur=getFail(last);
        if(!next[cur][c]){
            int now=newnode(len[cur]+2);
            fail[now]=next[getFail(fail[cur])][c];
            num[now]=num[fail[now]]+1;
            next[cur][c]=now;
        }
        last=next[cur][c];
        cnt[last]++;
        id[last]=n;
    }
    void count(){
        for(int i=p-1;i>=0;i--){
            cnt[fail[i]]+=cnt[i];
        }
    }
    int dfs(int u){
        ndp[u]=1;
        fdp[u]=0;
        //计算向上跳的fail指针次数,vis保证不重复(比如bb跳的fail指针,bbbb不能再跳),>1保证不走到奇偶根
        for(int t=u;!vis[t] && t>1;t=fail[t]){
            vis[t]=u;
            fdp[u]++;
        }
        for(int i=0;i<26;i++){
            if(next[u][i]){
                ndp[u]+=dfs(next[u][i]);
            }
        }
        //清空标记
        for(int t=u;vis[t]==u && t>1;t=fail[t]){
            vis[t]=0;
        }
        return ndp[u];
    }
    ll solve(){
        //从两个根dfs
        dfs(0);
        dfs(1);
        ll ans=0;
        for(int i=2;i<p;i++){
            //除去根,每个节点的贡献(作为另一个回文子串的子串)为
            //比如对于样例abba,回文节点bb的next指针指向abba,fail指针指向b
            //因此ndp和fdp都为2,贡献为2*2-1=3
            //即(b,bb) (b,abba) (bb,bb) (bb,abba),减1就是要减掉本身
            ans+=1ll*ndp[i]*fdp[i]-1;
        }
        return ans;
    };
}ac;
int T;
char s[N];
int main(void){
//    freopen("in.txt","r",stdin);
    scanf("%d",&T);
    for(int cas=1;cas<=T;cas++){
        scanf("%s",s);
        ac.init();
        int len=strlen(s);
        for(int i=0;i<len;i++){
            ac.add(s[i]);
        }
        ac.count();
        memset(vis,0,sizeof(vis));
        printf("Case #%d: %lld\n",cas,ac.solve());
    }
    return 0;
}

D Move

The meaning of problems

\ (n-\) th items, each having a volume \ (V_I \) , use \ (K \) boxes installed, greedy strategy is loaded from large to small, can be installed on the equipment, the minimum capacity of each box asking .

analysis

  • Since the greedy strategy, making box capacity is not monotone, there may be smaller capacity, but if the larger capacity may first fetched a number of large, resulting in too small just fit.

  • The simplest approach is to directly from the lower bound of the capacity of the \ (max (v_n, (sum -1) / k + 1) \) begins the enumeration of violence, and then determines multiset.

  • The upper bound of proof:
    • Suppose a capacity \ (V \) fit, then the remaining capacity is smaller than each box \ (MAXV \)
    • Then \ (k * (V-maxV + 1) <= sum \)
    • To give \ (V <= sum / k + maxV-1 \)
  • Since \ (v_i \) the range is relatively small, so you can understand the emotional moment, and then found that between half and then some violent district is also possible.

Code

#include <bits/stdc++.h>
using namespace std;
const int N=1005;
int T,n,k,a[N];
multiset<int> mt;
bool check(int x){
    mt.clear();
    for(int i=1;i<=n;i++){
        mt.insert(a[i]);
    }
    for(int i=0;i<k;i++){
        int u=0;
        while(u<x && !mt.empty()){
            auto p=mt.upper_bound(x-u);
            if(p==mt.begin()){
                break;
            }
            p--;
            u+=*p;
            mt.erase(p);
        }
    }
    return mt.empty();
}
int main(void){
//    freopen("in.txt","r",stdin);
    scanf("%d",&T);
    for(int cas=1;cas<=T;cas++){
        scanf("%d%d",&n,&k);
        int sum=0;
        for(int i=1;i<=n;i++){
            scanf("%d",&a[i]);
            sum+=a[i];
        }
        sort(a+1,a+1+n);
        //从下界暴力枚举
        int ans;
        for(int v=max(a[n],(sum-1)/k+1);;v++){
            if(check(v)){
                ans=v;
                break;
            }
        }
        printf("Case #%d: %d\n",cas,ans);
    }
    return 0;
}

G Is Today Friday?

The meaning of problems

Date string to n, A to J represents a 0 to 9 are arranged, a required minimum lexicographically arranged such that the n date is Friday.

analysis

  • Because of this restriction Friday, so for the first few dates, the first full array violence, to find out the whole arrangement to meet the conditions, and then judge the rest of the date from which the whole arrangement.

  • The calculated date may be several weeks or Zeller's congruence equation Kim Larsen

Code

#include <bits/stdc++.h>
using namespace std;
const int N=1e5+50;
int T,n;
struct node{
    char str[12];
    bool operator<(const node& rhs)const{
        return string(str)<string(rhs.str);
    }
    bool operator==(const node& rhs)const{
        return string(str)==string(rhs.str);
    }
}s[N];
vector<int> mp;
vector<vector<int> > ts;
int ms[]={0,31,28,31,30,31,30,31,31,30,31,30,31};
bool leap(int y){
    return ((y%4==0 && y%100!=0) || y%400==0);
}
//判断日期合法性
bool check(int y,int m,int d){
    if(m==0 || m>12 || d==0){
        return false;
    }
    int t=ms[m];
    if(leap(y) && m==2){
        t++;
    }
    return d<=t;
}
//基姆拉尔森公式
bool cl(int y,int m,int d){
    if(!check(y,m,d)){
        return false;
    }
    //题面...
    if(y<1600){
        return false;
    }
    //1 2月要转成上一年13 14月
    if(m<=2){
        m+=12;
        y--;
    }
    int w=((d+2*m+3*(m+1)/5+y+y/4-y/100+y/400+1)%7+7)%7;
    return w==5;
}
int main(void){
    // freopen("in.txt","r",stdin);
    scanf("%d",&T);
    for(int cas=1;cas<=T;cas++){
        scanf("%d",&n);
        for(int i=1;i<=n;i++){
            scanf("%s",s[i].str);
        }
        printf("Case #%d: ",cas);
        sort(s+1,s+1+n);
        int nn=unique(s+1,s+1+n)-s-1;
        //先根据前几个日期筛选出满足条件的全排列(不多),再代入剩下的日期判断
        //ts记得清空
        ts.clear();
        mp.clear();
        for(int i=0;i<10;i++){
            mp.push_back(i);
        }
        do{
            bool ac=true;
            //前4个
            for(int i=1;i<=min(nn,4);i++){
                int y=mp[s[i].str[0]-'A']*1000+mp[s[i].str[1]-'A']*100+mp[s[i].str[2]-'A']*10+mp[s[i].str[3]-'A'];
                int m=mp[s[i].str[5]-'A']*10+mp[s[i].str[6]-'A'];
                int d=mp[s[i].str[8]-'A']*10+mp[s[i].str[9]-'A'];
                if(!cl(y,m,d)){
                    ac=false;
                    break;
                }
            }
            if(ac){
                ts.push_back(mp);
            }
        }while(next_permutation(mp.begin(),mp.end()));
        //判断剩下n-4个
        int sz=ts.size();
//        for(int i=0;i<sz;i++){
//            for(int j=0;j<10;j++){
//                printf("%d",ts[i][j]);
//            }
//            printf("\n");
//        }
        //考虑nn<=4的情况
        if(nn<=4){
            if(sz){
                for(int i=0;i<10;i++){
                    printf("%d",ts[0][i]);
                }
                printf("\n");
            }else{
                printf("Impossible\n");
            }
            continue;
        }
        bool ok=false;
        for(int i=0;i<sz;i++){
            bool ac=true;
            for(int j=5;j<=nn;j++){
                int y=ts[i][s[j].str[0]-'A']*1000+ts[i][s[j].str[1]-'A']*100+ts[i][s[j].str[2]-'A']*10+ts[i][s[j].str[3]-'A'];
                int m=ts[i][s[j].str[5]-'A']*10+ts[i][s[j].str[6]-'A'];
                int d=ts[i][s[j].str[8]-'A']*10+ts[i][s[j].str[9]-'A'];
                if(!cl(y,m,d)){
                    ac=false;
                    break;
                }
            }
            if(ac){
                for(int j=0;j<10;j++){
                    printf("%d",ts[i][j]);
                }
                printf("\n");
                ok=true;
                break;
            }
        }
        if(!ok){
            printf("Impossible\n");
        }
    }
    return 0;
}

J Upgrading Technology

The meaning of problems

\ (n-\) skills, each skill has \ (m \) levels, the \ (I \) skills from \ (j-1 \) to rise to \ (J \) stage takes \ (c_ { } ij \) , \ (the n-\) skills have risen to \ (i \) level can be obtained income \ (D_i \) , ask the maximum benefit.

analysis

Implied meaning of the questions can \ (O (nm) \) complexity, so consider it an enumeration skills at the same time to rise to \ (i \) level, then the benefits can be obtained prefix and then enumerate the lowest level that is just \ (i \) level of skills, then take this skill can also be obtained prefix and, while other skills will be in \ (i \) behind the level just rose, we only need each skill in a pre-out after an upgrade of the level of minimum cost and minimum cost of n and skills.

Code

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1005;
int T,n,m;
ll c[N][N],d[N];
ll dp[N],cp[N][N];
ll mn[N][N],smn[N];
int main(void){
    freopen("in.txt","r",stdin);
    scanf("%d",&T);
    for(int cas=1;cas<=T;cas++){
        ll ans=0;
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++){
            cp[i][0]=0;
            for(int j=1;j<=m;j++){
                scanf("%lld",&c[i][j]);
                cp[i][j]=cp[i][j-1]+c[i][j];
            }
        }
        //mn[i][j]表示第i个技能从第j个等级开始的最小前缀和
        memset(smn,0,sizeof(smn));
        for(int i=1;i<=n;i++){
            mn[i][m]=cp[i][m];
            ll _mn=mn[i][m];
            smn[m]+=cp[i][m];
            for(int j=m-1;j>=0;j--){
                if(cp[i][j]<_mn){
                    _mn=cp[i][j];
                }
                mn[i][j]=_mn;
                smn[j]+=mn[i][j];
            }
        }
        dp[0]=0;
        for(int i=1;i<=m;i++){
            scanf("%lld",&d[i]);
            dp[i]=dp[i-1]+d[i];
        }
        for(int i=0;i<=m;i++){
            //枚举相同等级,可以都不升级
            for(int j=1;j<=n;j++){
                ll tmp=dp[i];
                //枚举最低等级的技能
                tmp-=cp[j][i];
                //剩下的技能找大于等于i级别的最小前缀和之和
                tmp-=smn[i];
                //最低等级的技能被重复减了
                tmp+=mn[j][i];
                ans=max(ans,tmp);
            }
        }
        printf("Case #%d: %lld\n",cas,ans);
    }
    return 0;
}

Guess you like

Origin www.cnblogs.com/zxcoder/p/11301002.html