Live2D

2020-11-25 考试总结

考得很炸,不是挂分太多了,主要是自己没想到,但是似乎不挂分排名还是比较好看的???

T1

水得一批,懒得讲。

T2 CF575A Fibonotci

题目传送门

思路

胡确实是很好胡,但是具体实现上面需要一定的技巧。于是借鉴了Rainybunny的Code

不难看出,如果没有修改操作,那么肯定是每 \(n\) 个数为一个循环段,每一个循环段某一个数与开头两个数相对关系确定。这个玩意就可以用矩阵进行优化。

考虑有修改,不难看出就是改了一个矩阵,具体来说可以直接拆开考虑。不过麻烦的地方就是如何考虑相邻的两处修改,其实你可以记录一下当前已经考虑了前面的多少位,通过判断当前位与修改点的关系判断这个矩阵是否被考虑到即可。具体可以见代码。

\(\texttt{Code}\)

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

#define Int register int
#define int long long
#define MAXN 50005

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,m,K,lg,mod,s[MAXN];
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;}

struct Matrix{
	int a,b,c,d;
	Matrix(){}
	Matrix (int _a,int _b,int _c,int _d){a = _a,b = _b,c = _c,d = _d;}
	Matrix operator * (const Matrix &p)const{return Matrix (add (mul (a,p.a),mul (b,p.c)),add (mul (a,p.b),mul (b,p.d)),add (mul (c,p.a),mul (d,p.c)),add (mul (c,p.b),mul (d,p.d)));}
}st[MAXN][65],tmp,ans;

void init (){
	for (Int i = 0;i < n;++ i) st[i][0] = Matrix (0,1,s[i],s[(i + 1) % n]);
	for (Int j = 1;(1ll << j) <= K;lg = j ++)
		for (Int i = 0;i < n;++ i)
			st[i][j] = st[(i + (1ll << j - 1)) % n][j - 1] * st[i][j - 1];
}

void getit (int& cur,int goal){
	for (Int i = lg;~i;-- i)
		if (cur + (1ll << i) < goal)
			ans = st[cur % n][i] * ans,cur += (1ll << i);
}

#define PII pair<int,int>
PII sk[MAXN];

signed main(){
	read (K,mod,n);
	if (mod == 1) return puts ("0"),0;
	for (Int i = 0;i < n;++ i) read (s[i]);
	init ();
	read (m);for (Int i = 1;i <= m;++ i){
		read (sk[i].first,sk[i].second);
		if (sk[i].first >= K) -- i,-- m; 
	}
	sort (sk + 1,sk + m + 1),ans.c = 1;int cur = 0;
	for (Int i = 1;i <= m;++ i){
		getit (cur,sk[i].first);
		if (cur < sk[i].first) tmp = Matrix (0,1,s[cur % n],sk[i].second),ans = tmp * ans,++ cur;
		if (i != m && sk[i + 1].first == sk[i].first + 1) tmp = Matrix (0,1,sk[i].second,sk[i + 1].second);
		else tmp = Matrix (0,1,sk[i].second,s[(cur + 1) % n]);
		ans = tmp * ans,++ cur;
	}
	getit (cur,K);
	write (cur < K ? ans.c : ans.a),putchar ('\n');
	return 0;
}

T3 CF480E Parking Lot

题目传送门

思路

原题做不出系列。。。

首先考虑 50 pts做法(我才不会告诉你我写的 \(nmk\log n\) 结果只有 10 pts),我们不难看出可以设 \(f_{i,j}\) 表示以 \((i,j)\) 为底部的最大正方形边长,可以得到转移式:

\[f_{i,j}=\min(f_{i-1,j},f_{i,j-1},f_{i-1,j-1})+1 \]

考虑 100 pts,不难看出正着做不好做,于是我们可以倒着做。于是要求的就是删除一个位置,包含这个位置的最大正方形边长。

这个比较好搞,我们可以用并查集维护一下空位,然后用单调性就可以做到 \(\Theta(nm)\)。(假设并查集是线性的。)

\(\texttt{Code}\) (一年前的代码了)

#include<bits/stdc++.h>
using namespace std;
const int maxn = 2e3 + 10;
int n,m,k;
int Ans;
int dp[maxn][maxn];
int l1[maxn];
int r1[maxn];
int qx[maxn];
int qy[maxn];
int ans[maxn];
char Map[maxn][maxn];

struct node
{
	int fa[maxn];
	int findSet (int x)
	{
		if (x == fa[x]) return x;
		else return fa[x] = findSet (fa[x]);
	}
}l[maxn],r[maxn];

void Delete(int x,int y)
{
	l[x].fa[y] = l[x].findSet(y - 1);
	r[x].fa[y] = r[x].findSet(y + 1);
}

int main()
{
	scanf("%d%d%d",&n,&m,&k);
	for(int i = 1; i <= n; i++)
		scanf("%s", Map[i]+1);
	for(int i = 1; i <= k; i++)
	{
		scanf("%d%d",&qx[i],&qy[i]);
		Map[qx[i]][qy[i]] = 'X';
	}
	for(int i = 1; i <= n; i++)
	{
		for(int j = 1; j <= m+1; j++)
		{
			l[i].fa[j] = j;
			r[i].fa[j] = j;
		}
	}
	for(int i = 1; i <= n; i++)
		for(int j = 1; j <= m; j++)
			if(Map[i][j] == '.')
				Delete(i, j);
	for(int i = 1; i <= n; i++)
		for(int j = 1; j <= m; j++)
			if(Map[i][j] == '.')
			{
				dp[i][j] = min(dp[i-1][j-1], min(dp[i-1][j],dp[i][j-1]))+1;
				Ans = max (Ans,dp[i][j]);
			}
	for (int j = k;j >= 1;-- j)
	{
		ans[j] = Ans;
		Delete (qx[j],qy[j]);
		for(int i = 1; i <= n; i++)
		{
			l1[i] = qy[j] - l[i].findSet(qy[j]);
			r1[i] = r[i].findSet(qy[j]) - qy[j];
		}
		for(int i = qx[j] + 1; i <= n; i++)
		{
			l1[i] = min(l1[i], l1[i - 1]);
			r1[i] = min(r1[i], r1[i - 1]);
		}
		for(int i = qx[j] - 1; i; i--)
		{
			l1[i] = min(l1[i], l1[i + 1]);
			r1[i] = min(r1[i], r1[i + 1]);
		}
		for(int i = 1; i <= qx[j]; i++)
			while(min(r1[i], r1[i + Ans]) + min(l1[i], l1[i + Ans]) - 1 > Ans)
				Ans++;
	}
	for(int i = 1; i <= k; i ++)
		printf("%d\n",ans[i]);
	return 0;
}

T4 ant

题目传送门

思路

不难看出 \(n^6\) 的高斯消元优化。

不难看出如果我们确定边界上的期望值,那我们就可以确定每一个点的 dp 值。于是拿这个解方程就可以做到 \(\Theta(n^3)\) 了。

\(\texttt{Code}\)

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

#define hash screwyourwholefamily
#define double long double
#define Int register int
#define get whysoserious
#define MAXN 205

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,m,x,y;
int hash (int x,int y){return !x ? y : m - 1 + x;}

struct node{
	double a[MAXN << 1];
}get[MAXN][MAXN];

double mat[MAXN][MAXN],f[MAXN];

signed main(){
//	freopen ("ant.in","r",stdin);
//	freopen ("ant.out","w",stdout);
	read (n,m,x,y);
	for (Int i = 0;i < m;++ i) get[0][i].a[hash (0,i)] = 1;
	for (Int i = 0;i < n;++ i) get[i][0].a[hash (i,0)] = 1;
	for (Int i = 1;i < n;++ i)
		for (Int j = 1;j < m;++ j){
			for (Int k = 0;k <= n + m - 1;++ k)
				get[i][j].a[k] = 0.5 * (get[i - 1][j].a[k] + get[i][j - 1].a[k]);
			get[i][j].a[n + m - 1] ++;
		}
	int up = n + m - 1;
	mat[0][0] = 1;
	for (Int i = 1;i < m;++ i){
		mat[hash (0,i)][hash (0,i)] = mat[hash (0,i)][up] = 2;
		for (Int j = 0;j <= up;++ j) if (j != up) mat[hash (0,i)][j] -= get[0][i - 1].a[j];else mat[hash (0,i)][j] += get[0][i - 1].a[j];
		for (Int j = 0;j <= up;++ j) if (j != up) mat[hash (0,i)][j] -= get[n - 1][i].a[j];else mat[hash (0,i)][j] += get[n - 1][i].a[j];
	}
	for (Int i = 1;i < n;++ i){
		mat[hash (i,0)][hash (i,0)] = mat[hash (i,0)][up] = 2;
		for (Int j = 0;j <= up;++ j) if (j != up) mat[hash (i,0)][j] -= get[i - 1][0].a[j];else mat[hash (i,0)][j] += get[i - 1][0].a[j];
		for (Int j = 0;j <= up;++ j) if (j != up) mat[hash (i,0)][j] -= get[i][m - 1].a[j];else mat[hash (i,0)][j] += get[i][m - 1].a[j];
	}	
	for (Int i = 0;i < up;++ i){
		int pos = i;
		for (Int j = i + 1;j < up;++ j) if (abs (mat[j][i]) > abs (mat[pos][i])) pos = j;
		if (abs (mat[pos][i]) < 1e-9) continue;
		if (pos ^ i) swap (mat[pos],mat[i]);
		for (Int j = i + 1;j < up;++ j){
			double d = mat[j][i] / mat[i][i];
			for (Int k = i;k <= up;++ k) mat[j][k] -= mat[i][k] * d; 
		} 
	}
	for (Int i = up - 1;~i;-- i){
		for (Int j = i + 1;j < up;++ j)
			mat[i][up] -= mat[i][j] * f[j];
		f[i] = mat[i][up] / mat[i][i];
	}
	double ans = get[x][y].a[up];
	for (Int i = 0;i < up;++ i) ans += get[x][y].a[i] * f[i];
	printf ("%.15Lf\n",ans);
	return 0;
}
posted @ 2020-11-25 21:23  Dark_Romance  阅读(107)  评论(0编辑  收藏  举报