noip模拟赛 #2

万年rk2

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

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

。。。

 

T1.不想写,等会放链接

T2

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

显然,二分极差

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

T3

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

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

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

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

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

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

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

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

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

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

于是就是$O(165^3 \times logn + T \times 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]],'\n');
        if(m == 2)write(ans[pos[0][1][0]],'\n');
        if(m == 3)write(ans[pos[0][0][1]],'\n');
    }
}
T3

 

posted @ 2018-09-20 19:28  探险家Mr.H  阅读(168)  评论(0编辑  收藏  举报