题解 合成史莱姆

传送门

  • 关于存在终止位置的随机游走:
    考虑令 \(f_i\) 为在所有时刻走到这个点上的点权和
    那么每个最终每个终止位置(到这样一个位置后便无法离开)停留的点的点权的期望即为

    \[周围点在所有时刻点权和的期望\times 周围点到这个点的概率 \]

于是 40 pts 的大力高斯消元可以写了
但是现在主元的个数还是 \(O(n)\) 级别的
若每个位置是一个变量,发现每个变量都与周围四个变量形成了一个方程
那么假如我们可以选定一些主元,将剩下的变量用与之相关的方程和选定的主元表示出来
那么这些主元的确切值可以用剩下没有用到的几个方程解出来

考虑这样一种构造方式
image

发现这些蓝色格子中的点是可以被表示的,并且类推可以表示全图
image

因为原图是凸的,而在一个凸多边形中放入一条斜率为 1 的线线长至多是 \(\sqrt S\) 级别的
所以这样需要的主元是 \(4\sqrt n\) 级别的
那么就可以高斯消元了,复杂度 \(O((sqrt n)^3)=O(n\sqrt n)\)
但是稍有一些细节而且我没空写了,所以代码咕了

点击查看写了一半的代码
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define N 100010
#define fir first
#define sec second
#define ll long long
//#define int long long

char buf[1<<21], *p1=buf, *p2=buf;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf, 1, 1<<21, stdin)), p1==p2?EOF:*p1++)
inline int read() {
	int ans=0, f=1; char c=getchar();
	while (!isdigit(c)) {if (c=='-') f=-f; c=getchar();}
	while (isdigit(c)) {ans=(ans<<3)+(ans<<1)+(c^48); c=getchar();}
	return ans*f;
}

int n;
ll ans[N];
bool vis[N];
int sum, tot;
pair<int, int> pos[N];
map<pair<int, int>, int> id;
const ll mod=998244353, inv4=748683265;
const int dlt[][2]={{-1,0},{1,0},{0,1},{0,-1}};
inline ll qpow(ll a, ll b) {ll ans=1; for (; b; a=a*a%mod,b>>=1) if (b&1) ans=ans*a%mod; return ans;}

namespace force{
	struct matrix{
		int n, m;
		double a[110][110];
		matrix() {n=m=0; memset(a, 0, sizeof(a));}
		matrix(int x, int y) {n=x; m=y; memset(a, 0, sizeof(a));}
		void resize(int x, int y) {n=x; m=y; memset(a, 0, sizeof(a));}
		inline double* operator [] (int t) {return a[t];}
		void put() {for (int i=1; i<=n; ++i) {for (int j=1; j<=m; ++j) cout<<a[i][j]<<' '; cout<<endl;}cout<<endl;}
		inline matrix operator * (matrix b) {
			matrix ans(n, b.m);
			for (int i=1; i<=n; ++i)
				for (int k=1; k<=m; ++k)
					for (int j=1; j<=b.m; ++j)
						ans[i][j]+=a[i][k]*b[k][j];
			return ans;
		}
	}mat, tr;
	inline matrix qpow(matrix a, ll b) {matrix ans=a; --b; for (; b; a=a*a,b>>=1) if (b&1) ans=ans*a; return ans;}
	inline ll qpow(ll a, ll b) {ll ans=1; for (; b; a=a*a%mod,b>>=1) if (b&1) ans=ans*a%mod; return ans;}
	map<pair<int, int>, int> id2;
	const double eps=1e-7;
	ll test(double val) {
		for (int i=1; i<=1000; ++i)
			for (int j=1; j<=1000; ++j)
				if (fabs(double(i)/double(j)-val)<eps) {
					// cout<<"val: "<<val<<' '<<i<<' '<<j<<endl;
					return i*qpow(j, mod-2)%mod;
				}
		// puts("not find");
		return 0;
	}
	void solve() {
		for (int i=1; i<=n; ++i) {
			for (int j=0; j<4; ++j) {
				pair<int, int> t={pos[i].fir+dlt[j][0], pos[i].sec+dlt[j][1]};
				if (id.find(t)==id.end()) {
					if (id2.find(t)==id2.end()) id2[t]=++tot;
				}
			}
		}
		mat.resize(1, tot);
		tr.resize(tot, tot);
		for (int i=1; i<=n; ++i) {
			if (vis[i]) mat[1][i]=1;
			for (int j=0; j<4; ++j) {
				pair<int, int> t={pos[i].fir+dlt[j][0], pos[i].sec+dlt[j][1]};
				if (id.find(t)==id.end()) tr[i][id2[t]]=0.25;
				else tr[i][id[t]]=0.25;
			}
		}
		for (int i=n+1; i<=tot; ++i) tr[i][i]=1;
		mat=mat*qpow(tr, 1e9);
		// cout<<"mat: "; for (int i=n+1; i<=tot; ++i) cout<<mat[1][i]<<' '; cout<<endl;
		ll sum=0;
		for (int i=n+1; i<=tot; ++i) {
			sum^=test(mat[1][i]);
		}
		cout<<sum<<endl;
	}
}

namespace task1{
	ll ans;
	struct matrix{
		int n, m;
		ll a[110][110];
		matrix() {n=m=0; memset(a, 0, sizeof(a));}
		matrix(int x, int y) {n=x; m=y; memset(a, 0, sizeof(a));}
		void resize(int x, int y) {n=x; m=y; memset(a, 0, sizeof(a));}
		inline ll* operator [] (int t) {return a[t];}
		void put() {for (int i=1; i<=n; ++i) {for (int j=1; j<=m; ++j) cout<<setw(10)<<a[i][j]<<' '; cout<<endl;}cout<<endl;}
		void gauss() {
			for (int i=1; i<=n; ++i) {
				for (int j=1; j<=n; ++j) if (i!=j) {
					ll t=a[j][i]*qpow(a[i][i], mod-2)%mod;
					for (int k=i; k<=m; ++k) a[j][k]=(a[j][k]-a[i][k]*t)%mod;
				}
			}
			for (int i=1; i<=n; ++i) a[i][m]=(a[i][m]*qpow(a[i][i], mod-2)%mod+mod)%mod;
		}
	}mat;
	void solve() {
		for (int i=1; i<=n; ++i) {
			for (int j=0; j<4; ++j) {
				pair<int, int> t={pos[i].fir+dlt[j][0], pos[i].sec+dlt[j][1]};
				if (id.find(t)==id.end()) pos[id[t]=++tot]=t;
			}
		}
		mat.resize(n, n+1);
		for (int i=1; i<=n; ++i) {
			mat[i][i]=-1; mat[i][n+1]=-vis[i];
			for (int j=0; j<4; ++j) {
				pair<int, int> t={pos[i].fir+dlt[j][0], pos[i].sec+dlt[j][1]};
				if (id[t]<=n) mat[i][id[t]]=inv4;
			}
		}
		// mat.put();
		mat.gauss();
		// mat.put();
		for (int i=n+1; i<=tot; ++i) {
			// cout<<"i: "<<i<<endl;
			ll sum=0;
			for (int j=0; j<4; ++j) {
				pair<int, int> t={pos[i].fir+dlt[j][0], pos[i].sec+dlt[j][1]};
				if (id.find(t)!=id.end() && id[t]<=n) sum+=mat[id[t]][n+1];
			}
			ans^=sum*inv4%mod;
		}
		cout<<ans<<endl;
	}
}

namespace task{
	ll ans;
	struct matrix{
		int n, m;
		ll a[510][510];
		matrix() {n=m=0; memset(a, 0, sizeof(a));}
		matrix(int x, int y) {n=x; m=y; memset(a, 0, sizeof(a));}
		void resize(int x, int y) {n=x; m=y; memset(a, 0, sizeof(a));}
		inline ll* operator [] (int t) {return a[t];}
		void put() {for (int i=1; i<=n; ++i) {for (int j=1; j<=m; ++j) cout<<setw(10)<<a[i][j]<<' '; cout<<endl;}cout<<endl;}
		void gauss() {
			for (int i=1; i<=n; ++i) {
				for (int j=1; j<=n; ++j) if (i!=j) {
					ll t=a[j][i]*qpow(a[i][i], mod-2)%mod;
					for (int k=i; k<=m; ++k) a[j][k]=(a[j][k]-a[i][k]*t)%mod;
				}
			}
			for (int i=1; i<=n; ++i) a[i][m]=(a[i][m]*qpow(a[i][i], mod-2)%mod+mod)%mod;
		}
	}mat;
	void solve() {
		for (int i=1; i<=n; ++i) {
			for (int j=0; j<4; ++j) {
				pair<int, int> t={pos[i].fir+dlt[j][0], pos[i].sec+dlt[j][1]};
				if (id.find(t)==id.end()) pos[id[t]=++tot]=t;
			}
		}
		int l=INF, r=-INF, u=-INF, d=INF;
		for (int i=1; i<=n; ++i) {
			l=min(l, pos[i].fir);
			r=max(r, pos[i].fir);
			u=max(u, pos[i].sec);
			d=min(d, pos[i].sec);
		}
		int ux=INF, dx=INF, ly=INF, ry=INF;
		for (int i=1; i<=n; ++i) {
			if (pos[i].fir==l) ly=min(ly, pos[i].sec);
			if (pos[i].fir==r) ry=min(ry, pos[i].sec);
			if (pos[i].sec==u) ux=min(ux, pos[i].fir);
			if (pos[i].sec==d) dx=min(dx, pos[i].fir);
		}
		int x=max(ux, dx), y=max(ly, ry);
		void spread()



		mat.resize(n, n+1);
		for (int i=1; i<=n; ++i) {
			mat[i][i]=-1; mat[i][n+1]=-vis[i];
			for (int j=0; j<4; ++j) {
				pair<int, int> t={pos[i].fir+dlt[j][0], pos[i].sec+dlt[j][1]};
				if (id[t]<=n) mat[i][id[t]]=inv4;
			}
		}
		// mat.put();
		mat.gauss();
		// mat.put();
		for (int i=n+1; i<=tot; ++i) {
			// cout<<"i: "<<i<<endl;
			ll sum=0;
			for (int j=0; j<4; ++j) {
				pair<int, int> t={pos[i].fir+dlt[j][0], pos[i].sec+dlt[j][1]};
				if (id.find(t)!=id.end() && id[t]<=n) sum+=mat[id[t]][n+1];
			}
			ans^=sum*inv4%mod;
		}
		cout<<ans<<endl;
	}
}

signed main()
{
	freopen("b.in", "r", stdin);
	freopen("b.out", "w", stdout);

	n=read();
	for (int i=1,x,y,t; i<=n; ++i) {
		x=read(); y=read();
		vis[id[{x, y}]=++tot]=read();
		pos[tot]={x, y};
		sum+=vis[tot];
	}
	// force::solve();
	task1::solve();

	return 0;
}
posted @ 2022-05-01 08:08  Administrator-09  阅读(4)  评论(0编辑  收藏  举报