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);
            }
        }
    }
  • 相关阅读:
    Poj 2017 Speed Limit(水题)
    Poj 1316 Self Numbers(水题)
    Poj 1017 Packets(贪心策略)
    Poj 1017 Packets(贪心策略)
    Poj 2662,2909 Goldbach's Conjecture (素数判定)
    Poj 2662,2909 Goldbach's Conjecture (素数判定)
    poj 2388 Who's in the Middle(快速排序求中位数)
    poj 2388 Who's in the Middle(快速排序求中位数)
    poj 2000 Gold Coins(水题)
    poj 2000 Gold Coins(水题)
  • 原文地址:https://www.cnblogs.com/cangT-Tlan/p/9690068.html
Copyright © 2011-2022 走看看