题解 合成史莱姆
- 关于存在终止位置的随机游走:
考虑令 \(f_i\) 为在所有时刻走到这个点上的点权和
那么每个最终每个终止位置(到这样一个位置后便无法离开)停留的点的点权的期望即为\[周围点在所有时刻点权和的期望\times 周围点到这个点的概率 \]
于是 40 pts 的大力高斯消元可以写了
但是现在主元的个数还是 \(O(n)\) 级别的
若每个位置是一个变量,发现每个变量都与周围四个变量形成了一个方程
那么假如我们可以选定一些主元,将剩下的变量用与之相关的方程和选定的主元表示出来
那么这些主元的确切值可以用剩下没有用到的几个方程解出来
考虑这样一种构造方式
发现这些蓝色格子中的点是可以被表示的,并且类推可以表示全图
因为原图是凸的,而在一个凸多边形中放入一条斜率为 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;
}