NOI 2017 Day1 题解

Posted Dark Romance

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了NOI 2017 Day1 题解相关的知识,希望对你有一定的参考价值。

被虐爆了。。。

T1 整数

题目传送门

Description

有一个整数 \\(x\\),有 \\(n\\) 此操作,每次操作为以下两种情况:

  • 给出 \\(a,b\\),将 \\(x\\) 加上 \\(a\\times 2^b\\)

  • 给出 \\(k\\),询问 \\(2^k\\) 位置的值(二进制下第 \\(k\\) 位)

\\(b\\le 30\\times n,a\\le 10^9\\)

Solution

做的时候特别愚蠢,写了一个 \\(\\Theta(30n\\log n)\\) 的代码交上去了。。。

实际上,我们可以直接暴力搞,我们可以每 \\(64\\) 位放进一个 \\(\\text{long long}\\) 里面,然后分别维护 \\(+,-\\) 的信息,直接暴力加到每一位上,这样的复杂度均摊是 \\(\\Theta(30n)\\) 的。

考虑如何计算一个位置的值,你发现只跟它及其它前面的值有关,所以只需要存一下 \\(+,-\\) 不一样的位置就好了。

复杂度 \\(\\Theta(n\\log n)\\) 的。

Code(嫖的wxk的,如有雷同绝非巧合)

#include <bits/stdc++.h>
using namespace std;

#define Int register int
#define MAXN 1000005

template <typename T> inline void read (T &t){t = 0;char c = getchar();int f = 1;while (c < \'0\' || c > \'9\'){if (c == \'-\') f = -f;c = getchar();}while (c >= \'0\' && c <= \'9\'){t = (t << 3) + (t << 1) + c - \'0\';c = getchar();} t *= f;}
template <typename T,typename ... Args> inline void read (T &t,Args&... args){read (t);read (args...);}
template <typename T> inline void write (T x){if (x < 0){x = -x;putchar (\'-\');}if (x > 9) write (x / 10);putchar (x % 10 + \'0\');}

int n,t1,t2,t3;

#define ull unsigned long long

set <int> dif;
ull val[2][MAXN];

void Addit (bool f,int whe){
	int b = whe >> 6,p = whe - (b << 6);ull tmp = val[f][b];
	if ((val[f][b] += 1ull << p) < tmp) Addit (f,b + 1 << 6);
	if (val[0][b] == val[1][b]) dif.erase (dif.find (b));
	else dif.insert (b);
}
 
bool query (int k){
	int b = k >> 6,p = k - (b << 6);
	bool f = (val[0][b] >> p & 1) != (val[1][b] >> p & 1);
	ull u0 = val[0][b] & (1ull << p) - 1,u1 = val[1][b] & (1ull << p) - 1;
	if (u0 != u1) return f ? u0 > u1 : u0 < u1;
	set <int>::iterator it = dif.lower_bound (b);
	if (it == dif.begin()) return f;
	else{
		-- it;
		return f ? val[0][*it] > val[1][*it] : val[0][*it] < val[1][*it];
	}
}

signed main(){
	read (n,t1,t2,t3);
	while (n --> 0){
		int t,a,b;read (t);bool f;
		if (t == 1){
			read (a,b),f = (a < 0),a = a < 0 ? -a : a;
			for (Int i = 0;(1 << i) <= a;++ i) if (a >> i & 1) Addit (f,b + i); 
		}
		else{
			int k;read (k);
			write (query (k)),putchar (\'\\n\'); 
		}
	}
	return 0;
}

T2 蚯蚓排队

题目传送门

Description

懒得写,看题面吧。

Solution

直接链表维护,写一个 hash 表就好了,复杂度均摊 \\(\\Theta(nk+ck^2+\\sum |s|)\\)

Code

懒得放了

T3 泳池

题目传送门

Description

有一个大小为 \\(n\\times 1001\\) 的矩阵,每个格子有 \\(p\\) 的概率有障碍,问以底为边的最大子矩阵大小为 \\(K\\) 的概率。

\\(n\\le 10^9,K\\le 10^3\\)

Solution

挺有意思的。

首先可以想到可以差分,即 \\(\\le K\\) 的概率减去 \\(\\le K-1\\) 的概率。分别求就好了,以下以 \\(K\\) 为例。

可以设 \\(f_{r,c}\\) 表示已经有 \\(r\\)\\(c\\) 列满足最大矩阵大小 \\(\\le K\\) 的概率,那我们就可以得到转移式:

\\[f_{r,c}=p^c\\times f_{r+1,c}+\\sum_{i=1}^{c} p^{i-1}\\times (1-p)\\times f_{r+1,i-1}\\times f_{r,c-i} \\]

边界就是当 \\(r\\times c>K\\) 的时候 \\(f_{r,c}=0\\),当 \\(c=0\\) 的时候 \\(f_{r,c}=1\\) 。答案即是 \\(f_{0,n}\\)

很显然,就不解释了。

然后你发现 \\(f_{0,x}\\) 只会跟 \\(f_{1,(0\\to k)}\\) 有关系,我们设 \\(G_{i}=p^{i}\\times (1-p)\\times f_{1,i},F_i=f_{0,i}\\),那么可以得到转移式:

\\[F_n=\\sum_{i=0}^{k+1} G_{i-1}\\times F_{n-i} \\]

然后你发现这个式子就是一个常系数齐次线性递推板子,就可以直接暴力多项式乘法以及多项式取模做到 \\(\\Theta(k^2\\log k)\\) 了。

Code

#include <bits/stdc++.h>
using namespace std;

#define Int register int
#define mod 998244353

template <typename T> inline void read (T &t){t = 0;char c = getchar();int f = 1;while (c < \'0\' || c > \'9\'){if (c == \'-\') f = -f;c = getchar();}while (c >= \'0\' && c <= \'9\'){t = (t << 3) + (t << 1) + c - \'0\';c = getchar();} t *= f;}
template <typename T,typename ... Args> inline void read (T &t,Args&... args){read (t);read (args...);}
template <typename T> inline void write (T x){if (x < 0){x = -x;putchar (\'-\');}if (x > 9) write (x / 10);putchar (x % 10 + \'0\');}

int n,K,x,y,p;
int mul (int a,int b){return 1ll * a * b % mod;}
int dec (int a,int b){return a >= b ? a - b : a + mod - b;}
int add (int a,int b){return a + b >= mod ? a + b - mod : a + b;}
int qkpow (int a,int b){
	int res = 1;for (;b;b >>= 1,a = mul (a,a)) if (b & 1) res = mul (res,a);
	return res;
}
void Add (int &x,int y){x = add (x,y);}
void Dec (int &x,int y){x = dec (x,y);}

#define MAXN 3005
int f[MAXN][MAXN],pw[MAXN];

int dfs (int r,int c,int k){
	if (~f[r][c]) return f[r][c];
	else if (r * c > k) return f[r][c] = 0;
	else if (c == 0) return f[r][c] = 1;
	else{
		f[r][c] = mul (pw[c],dfs (r + 1,c,k));
		for (Int i = 1;i <= c;++ i) Add (f[r][c],mul (mul (pw[i - 1],dec (1,p)),mul (dfs (r + 1,i - 1,k),dfs (r,c - i,k))));
		return f[r][c];
	}
}

int ls,lq,lg,A[MAXN],Q[MAXN],S[MAXN],G[MAXN],F[MAXN],tmp[MAXN];
void polymul (int a[],int b[],int c[],int &n,int m){
	for (Int i = 0;i <= n + m;++ i) tmp[i] = 0;
	for (Int i = 0;i <= n;++ i)
		for (Int j = 0;j <= m;++ j)
			Add (tmp[i + j],mul (b[i],c[j]));
	n += m;
	for (Int i = 0;i <= n + m;++ i) a[i] = tmp[i];
}

void polymod (int a[],int &n){
	for (Int i = n;i >= lq;-- i){
		if (!a[i]) continue;
		int tmp = mod - a[i];
		for (Int j = 0;j <= lq;++ j) Add (a[i - j],mul (tmp,Q[lq - j]));
	}n = min (n,lq - 1);
	while (n && !a[n]) -- n;
}

int calc (int N,int k){
	memset (Q,0,sizeof (Q)),memset (S,0,sizeof (S)),memset (G,0,sizeof (G));
	Q[lq = k] = 1;for (Int i = 0;i < k;++ i) Q[k - i - 1] = mod - A[i];
	S[0] = 1,G[1] = 1,ls = 0,lg = 1;
	while (N){
		if (N & 1) polymul (S,S,G,ls,lg),polymod (S,ls);
		polymul (G,G,G,lg,lg),polymod (G,lg);
		N >>= 1;
	}
	int res = 0;
	for (Int i = 0;i < k;++ i) Add (res,mul (F[i],S[i]));
	return res;
}

int Solve (int k){
	memset (f,-1,sizeof (f)),dfs (0,k,k),memset (F,0,sizeof (F)),memset (A,0,sizeof (A));
	for (Int i = 0;i <= k;++ i) F[i] = f[0][i],A[i] = mul (f[1][i],mul (pw[i],dec (1,p)));
	return calc (n,k + 1);
}

signed main(){
	read (n,K,x,y),p = mul (x,qkpow (y,mod - 2));
	pw[0] = 1;for (Int i = 1;i <= K;++ i) pw[i] = mul (pw[i - 1],p);
	if (n == 1) return write (mul (pw[K],dec (1,p))),putchar (\'\\n\') & 0;
	int v1 = Solve (K),v2 = Solve (K - 1);
	write (dec (v1,v2)),putchar (\'\\n\');
	return 0;
}
/*
f_{r,c}=p^c*f_{r+1,c}+\\sum_{i=1}^{c} p^(i-1)*(1-p)*f_{r+1,i-1}*f_{r,c-i}
*/

以上是关于NOI 2017 Day1 题解的主要内容,如果未能解决你的问题,请参考以下文章

NOI 2014简要题解

题解NOI2017游戏

BZOJ4942 & UOJ314:[NOI2017]整数——题解

FCS NOI2018福建省冬摸鱼笔记 day6FJOI 2018福建省选混分滚蛋记 day1

NOI2017总结

BZOJ4943 & 洛谷3823 & UOJ315:[NOI2017]蚯蚓排队——题解