$n \leq 200$个平面上的点,$q \leq 200$次询问:重复操作$m \leq 10000$次,到达点$x$的概率最大是多少。操作:一开始选点$P$,不一定要是给定点,可以是平面上任一点。然后,选一条穿过给定点至少两个点且穿过$P$的直线$l$,若有多条,等概率选一条;选中一条后,把$P$点移动到这条直线上的某个初始给定点,若有多个等概率选。

以为是不可做几何题,其实挺好玩的

如果知道两个点之间一次性直接到达的概率$A(x,y)$,那么记$f(i,j)$为走$i$步到点$j$的概率,$f(i,j)=\sum_{k=1}^{n}A(i,k)f(i-1,k)$,是个矩阵乘法,可以快速幂优化。后面$m-1$步可以用矩阵算,那第一步应该怎么选初始点呢?可以发现,固定了终点,用矩阵乘法推出了$f(m,i)$后,每条直线的贡献是固定的,而如果我们选的$P$点在几个直线的交汇处,得到的便是这几条直线贡献的平均值,这不如直接选一条贡献最大的直线(这里的选是说,把点P放在这条线上),而这总是可以做到的。因此输出答案最大的一条直线的答案即可。

有个问题,如果每次询问都要快速幂一次,那不久$qn^3logn$了吗?别担心,$A^{2^i}$是可以预处理的,等会要做乘法的时候只需拿$f$和某些$A^{2^i}$乘就好了,而一个一维数组$f$和矩阵的乘法是$n^2$的,如此少一个$n$,可通过。

通过个鬼。直线运算精度误差坑了我一个半小时。。这里上一个标程无误差版的板子:

struct line {
// ax + by + c = 0
int a, b, c; line() : a(), b(), c() { }
line(const point &p, const point &q)
: a(p.y - q.y)
, b(q.x - p.x)
, c(q.y * p.x - q.x * p.y)
{
int g = gcd(gcd(a, b), c);
if (g != ) { a /= g; b /= g; c /= g; }
if (a < ) { a = -a; b = -b; c = -c; }
} inline bool contains(const point &p) {
return a * p.x + b * p.y + c == ;
} // For sorting & duplicate removing
inline bool operator < (const line &other) const {
return a != other.a ? a < other.a :
b != other.b ? b < other.b : c < other.c;
}
inline bool operator == (const line &other) const {
return a == other.a && b == other.b && c == other.c;
}
};

以及我改longdouble终于通过的辣鸡版本:

 #include<iostream>
#include<cstring>
#include<cstdio>
#include<math.h>
//#include<complex>
//#include<set>
//#include<queue>
#include<vector>
#include<algorithm>
#include<stdlib.h>
using namespace std; #define double long double
#define LL long long
int qread()
{
char c; int s=,f=; while ((c=getchar())<'' || c>'') (c=='-') && (f=-);
do s=s*+c-''; while ((c=getchar())>='' && c<=''); return s*f;
} //Pay attention to '-' , LL and double of qread!!!! int n;
#define maxn 40011
#define maxm 40011
#define eps 1e-10
bool equ(double a,double b) {return fabs(a-b)<eps;}
bool neq(double a,double b) {return fabs(a-b)>eps;}
bool le(double a,double b) {return a-b<-eps;}
bool leq(double a,double b) {return a-b<eps;}
bool ge(double a,double b) {return a-b>eps;}
bool geq(double a,double b) {return a-b>-eps;} struct Point{int x,y;}p[maxn];
struct Line
{
double k,b;
void make(const Point &A,const Point &B)
{
if (A.x==B.x) {k=1e18; b=A.x; return;}
k=1.0*(A.y-B.y)/(A.x-B.x);
b=A.y-k*A.x;
}
bool operator < (const Line &l)
{
if (neq(l.k,k)) return le(k,l.k);
return le(b,l.b);
}
bool operator == (const Line &l) {return equ(l.k,k) && equ(l.b,b);}
bool operator != (const Line &l) {return !((*this)==l);}
}l[maxm]; int len=;
vector<int> vl[maxm],vp[maxn]; struct Mat
{
double a[][];
Mat() {memset(a,,sizeof(a));}
Mat operator * (const Mat &b)
{
Mat ans;
for (int i=;i<=n;i++)
for (int j=;j<=n;j++)
for (int k=;k<=n;k++)
ans.a[i][j]+=a[i][k]*b.a[k][j];
return ans;
}
}base[]; double f[maxn],g[maxn];
void mul(double *f,Mat b)
{
memset(g,,sizeof(g));
for (int j=;j<=n;j++)
for (int k=;k<=n;k++)
g[j]+=f[k]*b.a[j][k];
for (int j=;j<=n;j++) f[j]=g[j];
} int main()
{
n=qread();
for (int i=;i<=n;i++) {p[i].x=qread(); p[i].y=qread();}
for (int i=;i<=n;i++)
for (int j=i+;j<=n;j++)
{
len++;
l[len].make(p[i],p[j]);
}
sort(l+,l++len);
l[].k=l[len+].k=-1e18; l[].b=l[len+].b=-1e18;
{
int j=;
for (int i=;i<=len;i++) if (l[i]!=l[i-]) l[++j]=l[i];
len=j;
} for (int i=;i<=n;i++)
for (int j=;j<=len;j++)
if ((neq(l[j].k,1e18) && equ(l[j].k*p[i].x+l[j].b,p[i].y))
|| (equ(l[j].k,1e18) && equ(p[i].x,l[j].b)))
vl[j].push_back(i),vp[i].push_back(j); for (int i=;i<=n;i++)
for (int j=,to=vp[i].size();j<to;j++)
{
int u=vp[i][j];
for (int k=,too=vl[u].size();k<too;k++)
{
int x=vl[u][k];
base[].a[i][x]+=1.0/(to*too);
}
} for (int i=;i<=;i++) base[i]=base[i-]*base[i-];
int lq=qread(),x,y;
while (lq--)
{
x=qread(); y=qread(); y--;
memset(f,,sizeof(f)); f[x]=;
for (int i=;i<=;i++) if ((y>>i)&) mul(f,base[i]);
double ans=;
for (int i=;i<=len;i++)
{
double tmp=;
for (int j=,to=vl[i].size();j<to;j++) tmp+=f[vl[i][j]];
ans=max(ans,tmp/vl[i].size());
}
cout<<ans<<endl;
}
return ;
}

Codeforces989E. A Trance of Nightfall的更多相关文章

  1. Codeforces Round #487 (Div. 2) E. A Trance of Nightfall (矩阵优化)

    题意 有一个平面 , 给你 \(n\) 个点构成一个点集 \(S\) , 一开始可以选择一个平面上任意点 \(P\) . 存在一种操作 : 1 选择一条至少 通过 \(S\) 中任意两个点以及 \(P ...

  2. Codeforces 989E A Trance of Nightfall 矩阵快速幂+DP

    题意:二维平面上右一点集$S$,共$n$个元素,开始位于平面上任意点$P$,$P$不一定属于$S$,每次操作为选一条至少包含$S$中两个元素和当前位置$P$的直线,每条直线选取概率相同,同一直线上每个 ...

  3. Sunset: Nightfall Vulnhub Walkthrough

    靶机链接: https://www.vulnhub.com/entry/sunset-nightfall,355/ 主机扫描: ╰─ nmap -p- -A 10.10.202.162Starting ...

  4. 每日英语:Who Ruined The Humanities?

    You've probably heard the baleful reports. The number of college students majoring in the humanities ...

  5. 《图解HTTP》阅读笔记

    HTTP基础的简单理解 在了解HTTP协议之前,我们先了解下TCP/IP的参考模型,TCP/IP参考模型分为四层:应用层.传输层.网络层.链路层(数据链路层). 应用层:为不同的网络应用提供所需的服务 ...

  6. 现在开始(Do It Now)

    现在开始(Do It Now) 很多年前读大学的时候,我决定制定一个计划挑战自己:只用三个学期完成其他人通常花费四年的课程,能否毕业.这篇文章(此文为翻译)详细的说明了我在成功实现该目标过程中的所有时 ...

  7. ural 1250. Sea Burial

    1250. Sea Burial Time limit: 1.0 secondMemory limit: 64 MB There is Archipelago in the middle of a s ...

  8. Linux下编译内核配置选项简介

    Code maturity level options代码成熟度选项 Prompt for development and/or incomplete code/drivers 显示尚在开发中或尚未完 ...

  9. (转)TCP注册端口号大全

    分类: 网络与安全 cisco-sccp 2000/tcp Cisco SCCPcisco-sccp 2000/udp Cisco SCCp# Dan Wing <dwing&cisco ...

随机推荐

  1. C#传递数组参数

    在C#中,可以将数组作为参数传递给方法,同时方法可以更改数组元素的值. 一.将一维数组作为参数传递给方法 using System;using System.Collections.Generic;u ...

  2. Mutations-freecodecamp算法题目

    Mutations(比较字符串) 要求 如果数组第一个字符串元素包含了第二个字符串元素的所有字符,函数返回true. 不用考虑大小写和字符顺序 思路 将数组中的两个字符串小写化 将第二个数组元素(第二 ...

  3. 浅谈一类「AC自动机计数」问题

    最近写了几道AC自动机的题.这几题主要考察的是对AC自动机的浅层理解套上计数. 几道计数题 [AC自动机]bzoj3172: [Tjoi2013]单词 把被动贡献看成主动贡献. [状态压缩dp]119 ...

  4. 零拷贝详解 Java NIO学习笔记四(零拷贝详解)

    转 https://blog.csdn.net/u013096088/article/details/79122671 Java NIO学习笔记四(零拷贝详解) 2018年01月21日 20:20:5 ...

  5. GoF23种设计模式之结构型模式之装饰模式

    一.概述 动态地给一个对象添加一些额外的职责.装饰模式比生成子类更为灵活. 二.适用性 1.在不影响其他对象的情况下,以动态.透明的方式给但个对象添加职责. 2.处理那些可以撤销的职责. 3.当不能采 ...

  6. GoF23种设计模式之行为型模式之状态模式

    一.概述         定义对象之间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新. 二.适用性 1.一个对象的行为取决于它的状态,并且它必须在运行时刻 ...

  7. ProC第三弹

    一.前言 我们上面已经了解Windows和Linux下的ProC开发环境,这里我们更进一步去简要介绍下ProC的预编译参数. 二.什么是预编译 预编译过程中,Pro*C/C++会自动生成C或者C++的 ...

  8. 线段树:CDOJ1597-An easy problem C(区间更新的线段树)

    An easy problem C Time Limit: 4000/2000MS (Java/Others) Memory Limit: 65535/65535KB (Java/Others) Pr ...

  9. 制作iso文件

     genisoimage -o fusionstor-yi-2017-03-08.iso(镜像名称) -v -cache-inodes -joliet-long -R -J -T -V ZS  -c  ...

  10. MySQL-状态Waiting on empty queue引申

    MySQL 事件调度器示例演示 我们大家都知道MySQL 事件调度器是在 MySQL 5.1 中新生的一个较为特殊的功能,其可以作为定时任务调度器,来取代部分原先只能用操作系统任务调度器才能完成的定时 ...