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) << '\n';
    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 << "\n";
//    }
    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\n",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('\n');
            for(int k=0; k<27; ++k)
                if(ok3[i][j][k]) --tot,pc(i+'a'),pc(j+'a'),pc(k+'a'),pc('\n');
        }
    }
}

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\n",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\n",1-pw[sz[x]]);//Subtask2
        else printf("%.10lf\n",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\n",ans);
        }
    }
    return 0;
}
正解

 

posted @ 2018-09-22 18:04  落云小师妹  阅读(122)  评论(0编辑  收藏  举报