• noip模拟赛 #2


    万年rk2

    我写挂大家都挂但是有人比我挂的少

    我好不容易卡一波常数然后有人ak

    。。。

    T1.不想写,等会放链接

    T2

    给一个方阵,每个地方有一个权值,把它划成两块,不能往回拐弯,求两块极差较大的那个极差最小值是多少

    显然,二分极差

    然后贪心的画一条线,保证它不拐弯就可以了

    T3

    你下了一个$10^{18}$攻的克苏恩,对面有一个无限血的英雄和一个奴隶主,求这个克苏恩期望打多少下脸

    首先,只有7个格子,场面只跟奴隶主的血量有关(也没有火舌管站位干吗)

    然后我们可以搜一发状态,发现只有165个

    我们用$f_{i,s}$表示打了$i$下当前场面为$s$的期望打脸次数

    $s$怎么处理呢?哈希一下咯

    然后发现我们可以矩阵乘法,对于打脸的情况,另单开一行就可以了

    当然要记得自己转移自己...

    但这样还不够,复杂度$O(T imes 165^3 imes logn)$显然过不了

    考虑到最后我们只需要矩阵的一行中的几个元素而不是整个矩阵,又想到向量乘矩阵是$O(n ^ 2)$的

    我们可以预处理出转移矩阵的$2^t$次方,查询的时候相当于倍增,乘一次是$O(n ^ 2)$的

    于是就是$O(165^3 imes logn + T imes 165^2 logn)$的

    然而还是卡不过去,我们考虑优化取模,首先当然是要

    inline void add(LL &x,LL delt){x += delt;if(x >= mod)x -= mod;}

    其实这样加了O2我们已经可以过了

    然而本机1.5s的我还是慌得一批

    于是我们可以找一个很大的数,然后每次先膜这个大的,最后再膜998244353,$O(n^3)$次取膜变成了$O(n^2)$次的

    现在问题出在怎么找这个数上,一开始想的是找一个很大的质数,后来发现完全没必要质数,找一个20位左右的数就可以了

    这样就可以卡进1s了

    #include<bits/stdc++.h>
    #define LL long long
    using namespace std;
    inline int read()
    {
        int x = 0,f = 1;char ch = getchar();
        for(;!isdigit(ch);ch = getchar())if(ch == '-')f = -f;
        for(;isdigit(ch);ch = getchar())x = 10 * x + ch - '0';
        return x * f;
    }
    const int maxn = 2010;
    int h,w;
    int a[maxn][maxn],mn = 2147483233,mx;
    int l,r,ans;
    int chk(int mid)
    {
        int upb = mx - mid,lwb = mn + mid,j,lim = w + 1;
        for(int i=1;i<=h;i++)
        {
            for(j=1;j<lim;j++)if(a[i][j] < upb)break;
            lim = min(lim,j);
            for(j=lim;j<=w;j++)if(a[i][j] > lwb)return 0;
        }
        return 1;
    }
    void divide()
    {
        l = 0;
        while(l < r)
        {
            int mid = (l + r) >> 1;
            if(chk(mid))r = mid;
            else l = mid + 1;
        }
    }
    int main()
    {
        h = read(),w = read();
        for(int i=1;i<=h;i++)
            for(int j=1;j<=w;j++)
            {
                a[i][j] = read();
                mn = min(mn,a[i][j]);
                mx = max(mx,a[i][j]);
            }
        r = mx - mn;divide();
        for(int i=1;i<=h/2;i++)swap(a[i],a[h - i + 1]);divide();
        for(int i=1;i<=h;i++)reverse(a[i] + 1,a[i] + w + 1);divide();
        for(int i=1;i<=h/2;i++)swap(a[i],a[h - i + 1]);divide();
        cout<<r;
    }
    T2
    #include<bits/stdc++.h>
    #define LL unsigned long long
    using namespace std;
    inline LL read()
    {
        LL x = 0,f = 1;char ch = getchar();
        for(;!isdigit(ch);ch = getchar())if(ch == '-')f = -f;
        for(;isdigit(ch);ch = getchar())x = 10 * x + ch - '0';
        return x * f;
    }
    char buf[100010],top;
    
    inline void write(LL x,char opt = 0)
    {
        while(x)
        {
            buf[++top] = (char){x % 10 + '0'};
            x = x / 10;
        }
        for(;top;top--)putchar(buf[top]);
        if(opt)putchar(opt);
    }
    const LL mod = 998244353;
    const LL BIGNUM = (0x7fffffffffffffffll / mod - mod) * mod;
    inline void BIGADD(LL &x,LL delt)
    {
        x += delt;
        if(x >= BIGNUM)x -= BIGNUM;
    }
    int m,k;
    LL n;
    LL ans[170],tmp[170];
    int pos[10][10][10],dfn;
    struct Matrix
    {
        LL a[180][180];
        int w,h; 
        void init(int ww,int hh)
        {
            w = ww;h = hh;
            memset(a,0,sizeof(a));
        }
        Matrix operator * (const Matrix &b)const
        {
            Matrix res;
            res.init(h,b.w);
            for(int i=1;i<=h;i++)
                for(int j=1;j<=b.w;j++)
                {
                    for(int k=1;k<=w;k++)
                        BIGADD(res.a[i][j] , a[i][k] * b.a[k][j]);
                    res.a[i][j] %= mod;
                }
            return res;
        }
    }Vec[70];
    inline void Matrix_Mul_Vector(Matrix Trans,LL* w)
    {
        memset(tmp,0,sizeof(tmp));
        for(int i=1;i<=Trans.h;i++)
        {
            for(int j=1;j<=Trans.w;j++)
            {
                BIGADD(tmp[i] , Trans.a[i][j] * w[j]);
            }
            tmp[i] %= mod;
        }
        memcpy(w,tmp,sizeof(tmp));
    }
    
    inline LL ksm(LL x,LL k)
    {
        LL ans = 1;
        while(k)
        {
            if(k & 1)ans = (ans * x) % mod;
            x = (x * x) % mod;
            k = k >> 1;
        }
        return ans;
    }
    LL inve[10];
    int main()
    {
        //freopen("gen.in","r",stdin);
        //freopen("gen1.out","w",stdout);
        int T = read();m = read(),k = read();
        for(int i=1;i<=k+1;i++)inve[i] = ksm(i,mod - 2);
        //write(T);write(m);write(k);
        int lb,jb,ib;
        if(m > 2)lb = k;else lb = 0;
        for(int l=0;l<=lb;l++)
        {
            if(m > 1)jb = k - l;
            else jb = 0;
            for(int j=0;j<=jb;j++)
            {
                if(m)ib = k - j - l;
                else ib = 0;
                for(int i=0;i<=ib;i++)
                {
                    pos[i][j][l] = ++dfn;
                }
            }
        }
        for(int i=0;i<=63;i++)Vec[i].init(dfn + 1,dfn  + 1);
        if(m)ib = k;else ib = 0;
        for(int i=0;i<=ib;i++)
        {
            if(m > 1)jb = k - i;else jb = 0;
            for(int j=0;j<=jb;j++)
            {
                if(m > 2)lb = k - j - i;else lb = 0;
                for(int l=0;l<=lb;l++)
                {
                    int cnt = i + j + l,nowpos = pos[i][j][l],tolim = (cnt < k);
                    LL inv = inve[cnt + 1];
                    if(m == 1)
                    {
                        Vec[0].a[nowpos][pos[i - 1][0][0]] = (i * inv) % mod;
                    }
                    if(m == 2)
                    {
                        if(i != 0)Vec[0].a[nowpos][pos[i - 1][j][0]] = (i * inv) % mod;
                        if(j != 0)Vec[0].a[nowpos][pos[i + 1][j + tolim - 1][0]] = (j * inv) % mod; 
                    }
                    if(m == 3)
                    {
                        if(i != 0)Vec[0].a[nowpos][pos[i - 1][j][l]] = (i * inv) % mod;
                        if(j != 0)Vec[0].a[nowpos][pos[i + 1][j - 1][l + tolim]] = (j * inv) % mod;
                        if(l != 0)Vec[0].a[nowpos][pos[i][j + 1][l + tolim - 1]] = (l * inv) % mod;
                    }
                    Vec[0].a[nowpos][nowpos] = Vec[0].a[nowpos][dfn + 1] = inv;
                }
            }
        }
        Vec[0].a[dfn + 1][dfn + 1] = 1;
        for(int i=1;i<=63;i++)Vec[i] = Vec[i - 1] * Vec[i - 1];
        while(T--)
        {
            n = read();
            memset(ans,0,sizeof(ans));
            ans[dfn + 1] = 1;
            for(int l=0;l<=60;l++)
                if(n & (1LL << l))Matrix_Mul_Vector(Vec[l],ans);
            if(m == 1)write(ans[pos[1][0][0]],'
    ');
            if(m == 2)write(ans[pos[0][1][0]],'
    ');
            if(m == 3)write(ans[pos[0][0][1]],'
    ');
        }
    }
    T3
  • 相关阅读:
    贝叶斯定理
    用matplotlib统计数据并画图
    词云图
    一行python代码能写出啥?
    用python生成二维码
    18个python的高效编程技巧
    django简介
    vue点击变色
    selenium破解人人登陆验证码
    selenium请求豆瓣网
  • 原文地址:https://www.cnblogs.com/Kong-Ruo/p/9682814.html
Copyright © 2020-2023  润新知