zoukankan      html  css  js  c++  java
  • 18.9.22 noip模拟赛

    此题为找规律。期望100 实际100

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    long long len1,len2;
    long long n,s1,t1,s2,t2;
    long long abss(long long x){
        if(x<0)    return -x;
        else return x;
    }
    long long maxx(long long x,long long y){
        if(x>y)    return x;
        else return y;
    }
    int main(){
        freopen("grid.in","r",stdin);
        freopen("grid.out","w",stdout);
        cin>>n>>s1>>t1>>s2>>t2;
        len1=abss(s1-s2);len2=abss(t1-t2);
        cout<<maxx(len1,len2)<<endl;
    }

     期望20~40  实际20  感觉第二部分的部分分可以枚举所有可行的字符串,然后判断是否可行,但是炸掉了。

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    int T,type,n,tot,num;
    char s[50010];
    string ans[130000];
    void dfs(int be,string sbef){
        string smid;
        for(int i=be;i>=3;i--){
            smid+=s[i];
            int lenn=smid.length();
            if(type==0){
                if(smid!=sbef)
                if(smid.length()==2||smid.length()==3){
                    ans[++num]=smid;
                    dfs(i-1,smid);
                }
            }
            else{
                if(smid.length()==2||smid.length()==3){
                    ans[++num]=smid;
                    dfs(i-1,smid);
                }
            }
            if(smid.length()>3)    break;
        }
    }
    int main(){
        freopen("ling.in","r",stdin);
        freopen("ling.out","w",stdout);
        scanf("%d%d",&T,&type);
        while(T--){
            cin>>s;
            int len=strlen(s);
            if(len<=20){
                dfs(len-1,"abcd");
                for(int i=1;i<=num;i++){
                    int lenn=ans[i].length();
                    string simm=ans[i];
                    for(int j=0;j<lenn;j++)
                        ans[i][j]=simm[lenn-j-1];
                }
                sort(ans+1,ans+1+num);
                for(int i=1;i<=num;i++)
                    if(ans[i]!=ans[i-1])    tot++;
                cout<<tot<<endl;
                for(int i=1;i<=num;i++)
                    if(ans[i]!=ans[i-1])    cout<<ans[i]<<endl;
                num=0;tot=0;
            }
            else if(type==1){
                for(int i=len-1;i>=3;i-=3){
                    string smid;
                    for(int j=i;j>=3;j--){
                        smid+=s[j];
                        if(i-j==2||i-j==1)
                            ans[++num]=smid;
                        if(i-j>2)    break;
                    }
                }
                for(int i=len-1;i>=3;i-=2){
                    string smid;
                    for(int j=i;j>=3;j--){
                        smid+=s[j];
                        if(i-j==2||i-j==1)
                            ans[++num]=smid;
                        if(i-j>2)    break;
                    }
                }
                for(int i=1;i<=num;i++){
                    int lenn=ans[i].length();
                    string simm=ans[i];
                    for(int j=0;j<lenn;j++)
                        ans[i][j]=simm[lenn-j-1];
                }
                sort(ans+1,ans+1+num);
                for(int i=1;i<=num;i++)
                    if(ans[i]!=ans[i-1])    tot++;
                cout<<tot<<endl;
                for(int i=1;i<=num;i++)
                    if(ans[i]!=ans[i-1])    cout<<ans[i]<<endl;
                num=0;tot=0;
            }
        }
    }
    View Code

    我们只要知道上次填的串多长,就可以知道上次使用的字符串。而且
    对每个位置只需要知道它上次填2或3时是否可行。
    f[i][2或3]表示当前到i,填以i开头、长度为2或3的后缀串是否可行。可以转移就记录答案。

    如果typt!=0则不需要判后缀是否相同。
    复杂度O(n) 。
    为了方便可以把串反过来。

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define pc putchar
    using namespace std;
    const int N=50005;
    bool f[N][2],ok2[28][28],ok3[28][28][28];
    char s[N];
    void Work(const int type){
        memset(f,0,sizeof f);
        memset(ok2,0,sizeof ok2), memset(ok3,0,sizeof ok3);
        scanf("%s",s+1);
        int n=strlen(s+1);
        std::reverse(s+1,s+1+n);
        int tot=0; n-=3;
        if(n>=2) f[2][0]=1, ++tot, ok2[s[2]-'a'][s[1]-'a']=1;
        if(n>=3) f[3][1]=1, ++tot, ok3[s[3]-'a'][s[2]-'a'][s[1]-'a']=1;
        for(int i=4; i<=n; ++i){
            int a=s[i]-'a', b=s[i-1]-'a', c=s[i-2]-'a';
            if(f[i-2][1]||(f[i-2][0]&&(type||s[i]!=s[i-2]||s[i-1]!=s[i-3]))){
                f[i][0]=1;
                if(!ok2[a][b]) ++tot, ok2[a][b]=1;
            }
            if(f[i-3][0]||(f[i-3][1]&&(type||s[i]!=s[i-3]||s[i-1]!=s[i-4]||s[i-2]!=s[i-5]))){
                f[i][1]=1;
                if(!ok3[a][b][c]) ++tot, ok3[a][b][c]=1;
            }
        }
        printf("%d
    ",tot);
        for(int i=0; i<27&&tot; ++i){
            for(int j=0; j<27; ++j){
                if(ok2[i][j]) --tot,pc(i+'a'),pc(j+'a'),pc('
    ');
                for(int k=0; k<27; ++k)
                    if(ok3[i][j][k]) --tot,pc(i+'a'),pc(j+'a'),pc(k+'a'),pc('
    ');
            }
        }
    }
    int main(){
        int T,type;
        for(scanf("%d%d",&T,&type); T--; Work(type));
        return 0;
    }

    期望10   实际10

     也就只会写他是条链的暴力了。

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    int T,q,num=1,tot,deepmax;
    long double ans;
    int son[500010],deep[500010];
    int to[500010],net[500010],head[500010];
    void add(int u,int v){
        to[++tot]=v;net[tot]=head[u];head[u]=tot;
    }
    long double pow(long double x,int num){
        long double bns=x;
        for(int i=1;i<num;i++)
            bns*=x;
        return bns;
    }
    void work(int now,int de){
        for(int i=head[now];i;i=net[i]){
            deep[de]+=son[to[i]];
            deepmax=(deepmax,de);
            work(to[i],de+1);
        }
    }
    int main(){
        freopen("threebody.in","r",stdin);
        freopen("threebody.out","w",stdout);
        scanf("%d%d",&T,&q);
        if(q>2000&&q<=3000){
            for(int i=1;i<=q;i++){
                int x,y;
                scanf("%d%d",&x,&y);
                if(x==1)    num++;
                else if(x==2){
                    for(int j=0;j<num-y;j++)
                        ans+=pow(0.5,j+1)*j;
                    ans+=pow(0.5,num-y)*(num-y);
                    printf("%.10lf
    ",double(ans));
                }
                ans=0;
            }
        }
        else{
            for(int i=1;i<=q;i++){
                int x,y;
                scanf("%d%d",&x,&y);
                if(x==1){
                    num++;son[y]++;
                    add(y,num);
                }
                else if(x==2){
                    deep[1]=son[y];
                    work(y,2);
                    /*for(int j=1;j<=deepmax;j++)    cout<<deep[i]<<" ";cout<<endl;*/
                    for(int j=1;j<=deepmax;j++){
                        long double bns=1.0;
                        for(int k=1;k<=j;k++)
                            bns=bns*(1-pow(0.5,deep[k]));
                        bns=bns*pow(0.5,deep[j+1]);
                        ans+=bns*j;
                    }
                    printf("%.10lf
    ",double(ans));
                    ans=0;
                }
            }
        }
    }
    /*
    0 6
    2 1
    1 1
    1 2
    1 3
    1 4
    2 1
    */
    View Code

     std

    首先我们不需要考虑很大的深度。假如换h=100 ,需要一条长100 的链,即至少同时存在100 条
    边,概率为,非常小。设需考虑的最大高度

    对于询问,只要x 有一个子树的深度为h 且其它子树深度不超过 h,就可以用p(h)*h 更新答案。
    所以记f[x ][h]表示以 x为根,deep[x]<=h 的概率。则答案为

    考虑如何从 转移。每个子节点有两种情况,一是存在边,对f[x][h] 贡献 1/2*f[v][h-1]的概率;二是不存在该边,概率为1/2 。

    类似多项式,把 项乘在一起,即

    (比如,深度为0,对应 深度为1,对应 个 1/2与一个……

    复杂度

    如果新建节点 ,则影响的点有

    因为深度不超过70 ,所以暴力向上更新即可,也就是除掉之前的项,乘上新的项。

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define MAX_H 60
    #define MAXN 500010
    using namespace std;
    int T,Q,n,fa[MAXN];
    double f[MAXN][MAX_H];
    int main(){
        n=1;scanf("%d%d",&T,&Q);
        for(int i=0;i<MAX_H;i++)    f[1][i]=1;
        while(Q--){
            int opt,x;
            scanf("%d%d",&opt,&x);
            if(opt==1){
                fa[++n]=x;
                for(int i=0;i<MAX_H;i++)    f[n][i]=1;
                double tmp1=f[x][0],tmp2;
                f[x][0]*=0.5;
                for(int Fa=fa[x],i=1;Fa&&i<MAX_H;Fa=fa[x=Fa],i++){
                    tmp2=f[Fa][i];
                    f[Fa][i]/=0.5+0.5*tmp1;
                    f[Fa][i]*=0.5+0.5*f[x][i-1];
                    tmp1=tmp2;
                }
            }
            else {
                double ans=0;
                for(int i=1;i<MAX_H;i++)    ans+=(f[x][i]-f[x][i-1])*i;
                printf("%.10lf
    ",ans);
            }
        }
    }
  • 相关阅读:
    Golang的类型转换实战案例
    Golang的基础数据类型-布尔型
    Golang的运算符优先级实操案例
    Golang的单目(一元)运算符-地址操作符和接收操作符
    基于Ambari的WebUI部署kafka服务
    HBase集群优化篇
    HBase Master的高可用实战案例
    HBase 数据迁移实战案例
    HBase API实战案例
    MySQL数据源接入DBus
  • 原文地址:https://www.cnblogs.com/cangT-Tlan/p/9690068.html
Copyright © 2011-2022 走看看