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; }
#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'); } }