zoukankan      html  css  js  c++  java
  • 18/9/22NOIP模拟考

            18/9/22NOIP模拟考

    其实本来是有多组数据的,出题人忘记在题面上加了   斜眼笑

     期望得分:100;实际得分:100

    由于种种原因,拿到题的时候已经过去了0.5h+。。。

    然后因为这道题数据范围比较大,所以。。就想到了找规律

    没想到居然A了  开心

    这道题一共出现了三种做法:

    1.出题人的std:据说是旋转坐标系什么鬼的,没听说过。。。

    2.某人:从一个点做一个斜率为±1的一次函数,然后。。。如图

    3.大部分人(包括我):分别求出两点横纵坐标之差的绝对值,然后取max,完事

    4.极少部分人:模拟 or 暴力?

    #include <algorithm>
    #include <iostream>
    #include <cstring>
    #include <cstdlib>
    #include <cstdio>
    using namespace std;
    typedef long long LL;
    LL n, s, t, c, f;
    
    int main() {
        freopen("grid.in","r",stdin);
        freopen("grid.out","w",stdout);
        scanf("%I64d%I64d%I64d%I64d%I64d", &n, &s, &t, &c, &f);
        LL a = abs(s - c), b = abs(t - f);
        cout << max(a, b) << '
    ';
        fclose(stdin); fclose(stdout);
        return 0;
    }
    极其简短的我的代码 qwq
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<iostream>
    #include<cctype>
    #include<cmath>
    #include<set>
    #include<map>
    #include<queue>
    #include<vector>
    #include<cassert>
    using namespace std;
    typedef long long LL;
    
    inline int read() {
        int x = 0, f = 1; char ch = getchar(); for (; !isdigit(ch); ch=getchar()) if (ch=='-') f = -1;
        for (; isdigit(ch); ch=getchar()) x = x * 10 + ch - '0'; return x * f;
    }
    
    LL dx[4] = {0, 0, 1, -1};
    LL dy[4] = {1, -1, 0, 0};
    
    LL getdis(LL a,LL b,LL c,LL d,int flag) {
        if (flag) { // black
            a = (a - 1) / 2, b = (b - 1) / 2, c = (c - 1) / 2, d = (d - 1) / 2;
            return abs(a - c) + abs(b - d);
        }
        else { // white
            a /= 2, b /= 2, c /= 2, d /= 2;
            return abs(a - c) + abs(b - d);
        }
    }
    void getxy(LL a,LL b,LL &t1,LL &t2) {
        t1 = a + b,t2 = b - a;
    }
    int main() {
        
        freopen("grid.in","r",stdin);
        freopen("grid.out","w",stdout);
        
        LL Case,n, a, b, c, d, t1, t2, t3, t4, t5, t6;
    //    cin >> Case;
    //    while (Case--) {
            
            cin >> n >> a >> b >> c >> d;
            
            assert(a <= n);
            assert(b <= n);
            assert(c <= n);
            assert(d <= n);
            
            t1 = a + b, t2 = b - a;
            t3 = c + d, t4 = d - c;
            
            int f1, f2; 
            if ((t1 & 1) && (t2 & 1)) f1 = 1;
            else f1 = 0;
            if ((t3 & 1) && (t4 & 1)) f2 = 1;
            else f2 = 0;
            
            LL ans = 1e18;
            if (f1 == f2) ans = getdis(t1, t2, t3, t4, f1);
            else {
                for (int i=0; i<4; ++i) {
                    LL x = a + dx[i], y = b + dy[i];
                    if (x >= 1 && x <=n && y >= 1 && y <= n) {
                        getxy(x, y, t5, t6);
                        ans = min(ans, getdis(t3, t4, t5, t6, f2) + 1);
                    }
                }
                for (int i=0; i<4; ++i) {
                    LL x = c + dx[i], y = d + dy[i];
                    if (x >= 1 && x <=n && y >= 1 && y <= n) {
                        getxy(x, y, t5, t6);
                        ans = min(ans, getdis(t1, t2, t5, t6, f1) + 1);
                    }
                }
            }
            cout << ans << "
    ";
    //    }
        return 0;
    }
    std

     期望得分:0;实际得分:0

    其实还是希望有些分的,然而暴力没有调出来。。。

    然后就gg了 qwq

    正解:如果写了dfs的话,可以看出:我们只要知道上次填的串多长,就可以知道上次使用的字符串。而且对每个位置只需要知道它上次填2或3时是否可行。

    $f[i][2/3]$表示当前到$i$,以$i$开头,长度为2/3的的后缀串是否可行。可以转移就记录答案。

    如果type ≠ 0,则不需要判断后缀是否相同

    为了方便,可以把串反过来

    复杂度:O(n)

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #define pc putchar
    const int N=50005;
    
    bool f[N][2]/*0:2 1:3*/,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])))//i>=6
            {
                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() {
        freopen("ling.in","r",stdin);
        freopen("ling.out","w",stdout);
    
        int T,type;
        for(scanf("%d%d",&T,&type); T--; Work(type));
        return 0;
    }
    std

     

    一看要求期望。。。一脸不可做。。。

    整场考试也就瞄了几眼,一点想做的念头都没有。。。

    蒻的一批。。。

    事实证明,真心难啊 qwq

    #include <cstdio>
    #include <cctype>
    #include <assert.h>
    #include <algorithm>
    #define gc() getchar()
    const int N=5e5+5;
    
    int n,sz[N],fa[N],q[N],H[N],Enum,to[N],nxt[N];
    double pw[N];//2^{-i}
    
    inline int read() {
        int now=0;register char c=gc();
        for(;!isdigit(c);c=gc());
        for(;isdigit(c);now=now*10+c-'0',c=gc());
        return now;
    }
    inline void AddEdge(int u,int v) {
        fa[v]=u, ++sz[u], ++sz[fa[u]];
        to[++Enum]=v, nxt[Enum]=H[u], H[u]=Enum;
    }
    double Calc(int x) {
        if(!sz[x]) return 0;//sz:子树内点数 
        int t=0;//t:子节点数 
        for(int i=H[x]; i; i=nxt[i]) q[t++]=to[i];
        if(t==sz[x])//D=2
            return 1-pw[t];
        else     {
            double ans=0;
            for(int s=1; s<1<<t; ++s) {
                int tot=0;
                for(int i=0; i<t; ++i)
                    if(s>>i&1)
                        for(int j=H[q[i]]; j; j=nxt[j])
                            assert(!H[to[j]]), ++tot;
                ans+=pw[t]*(pw[tot]*1+(1-pw[tot])*2);
            }
            return ans;
        }
    }
    void Subtask3(int Q) {
        static int dep[N];
        int H=0; dep[1]=0;
        while(Q--) {
            int opt=read(),x=read();
            if(opt==1) dep[++n]=++H;
            else {
                int h=H-dep[x];
                double ans=h*pw[h];
                for(int i=1; i<h; ++i) ans+=i*pw[i+1];
                printf("%.10lf
    ",ans);
            }
        }
    }
    
    int main() {
        freopen("threebody.in","r",stdin);
        freopen("threebody.out","w",stdout);
    
        n=1;
        int T=read(), Q=read(); pw[0]=1;
        for(int i=1; i<=Q; ++i) pw[i]=pw[i-1]*0.5;
    
        if(T==4) {Subtask3(Q); return 0;}
    
        while(Q--) {
            int opt=read(),x=read();
            if(opt==1) AddEdge(x,++n);
            else if(T==3) printf("%.10lf
    ",1-pw[sz[x]]);//Subtask2
            else printf("%.10lf
    ",Calc(x));//Subtask1
        }
        return 0;
    }
    subtask1.2.3.
    #include <cstdio>
    #include <cctype>
    #include <assert.h>
    #include <algorithm>
    #define gc() getchar()
    #define MAX_H 60
    const int N=5e5+5;
    
    int n,fa[N];
    double f[N][MAX_H];
    
    inline int read() {
        int now=0;register char c=gc();
        for(;!isdigit(c);c=gc());
        for(;isdigit(c);now=now*10+c-'0',c=gc());
        return now;
    }
    
    int main() {
        freopen("threebody.in","r",stdin);
        freopen("threebody.out","w",stdout);
    
        n=1;
        for(int i=0; i<MAX_H; ++i) f[1][i]=1;
        for(int T=read(), Q=read(); Q--; ) {
            int opt=read(),x=read();
            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; assert(x<=n);
                for(int i=1; i<MAX_H; ++i) ans+=(f[x][i]-f[x][i-1])*i;
                printf("%.10lf
    ",ans);
            }
        }
        return 0;
    }
    正解
  • 相关阅读:
    eclipse workspace
    logcat and monkey
    git command
    Take Total Control of Internet Explorer with Advanced Hosting Interfaces
    #import 指令
    今天聊发兴致,写了一个 COM STEP BY STEP,结果。。。
    DECLARE_CLASSFACTORY_SINGLETON 宏
    对象微操
    宏定义缺失的解决
    读取地址本内容
  • 原文地址:https://www.cnblogs.com/v-vip/p/9690750.html
Copyright © 2011-2022 走看看