zoukankan      html  css  js  c++  java
  • Codeforces989E. A Trance of Nightfall

    $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(0), b(0), c(0) { }
        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 != 1) { a /= g; b /= g; c /= g; }
            if (a < 0) { a = -a; b = -b; c = -c; }
        }
    
        inline bool contains(const point &p) {
            return a * p.x + b * p.y + c == 0;
        }
    
        // 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终于通过的辣鸡版本:

      1 #include<iostream>
      2 #include<cstring>
      3 #include<cstdio>
      4 #include<math.h>
      5 //#include<complex>
      6 //#include<set>
      7 //#include<queue>
      8 #include<vector>
      9 #include<algorithm>
     10 #include<stdlib.h>
     11 using namespace std;
     12 
     13 #define double long double
     14 #define LL long long
     15 int qread()
     16 {
     17     char c; int s=0,f=1; while ((c=getchar())<'0' || c>'9') (c=='-') && (f=-1);
     18     do s=s*10+c-'0'; while ((c=getchar())>='0' && c<='9'); return s*f;
     19 }
     20 
     21 //Pay attention to '-' , LL and double of qread!!!!
     22 
     23 int n;
     24 #define maxn 40011
     25 #define maxm 40011
     26 #define eps 1e-10
     27 bool equ(double a,double b) {return fabs(a-b)<eps;}
     28 bool neq(double a,double b) {return fabs(a-b)>eps;}
     29 bool le(double a,double b) {return a-b<-eps;}
     30 bool leq(double a,double b) {return a-b<eps;}
     31 bool ge(double a,double b) {return a-b>eps;}
     32 bool geq(double a,double b) {return a-b>-eps;}
     33 
     34 struct Point{int x,y;}p[maxn];
     35 struct Line
     36 {
     37     double k,b;
     38     void make(const Point &A,const Point &B)
     39     {
     40         if (A.x==B.x) {k=1e18; b=A.x; return;}
     41         k=1.0*(A.y-B.y)/(A.x-B.x);
     42         b=A.y-k*A.x;
     43     }
     44     bool operator < (const Line &l)
     45     {
     46         if (neq(l.k,k)) return le(k,l.k);
     47         return le(b,l.b);
     48     }
     49     bool operator == (const Line &l) {return equ(l.k,k) && equ(l.b,b);}
     50     bool operator != (const Line &l) {return !((*this)==l);}
     51 }l[maxm]; int len=0;
     52 vector<int> vl[maxm],vp[maxn];
     53 
     54 struct Mat
     55 {
     56     double a[211][211];
     57     Mat() {memset(a,0,sizeof(a));}
     58     Mat operator * (const Mat &b)
     59     {
     60         Mat ans;
     61         for (int i=1;i<=n;i++)
     62             for (int j=1;j<=n;j++)
     63                 for (int k=1;k<=n;k++)
     64                     ans.a[i][j]+=a[i][k]*b.a[k][j];
     65         return ans;
     66     }
     67 }base[20];
     68 
     69 double f[maxn],g[maxn];
     70 void mul(double *f,Mat b)
     71 {
     72     memset(g,0,sizeof(g));
     73     for (int j=1;j<=n;j++)
     74         for (int k=1;k<=n;k++)
     75             g[j]+=f[k]*b.a[j][k];
     76     for (int j=1;j<=n;j++) f[j]=g[j];
     77 }
     78 
     79 int main()
     80 {
     81     n=qread();
     82     for (int i=1;i<=n;i++) {p[i].x=qread(); p[i].y=qread();}
     83     for (int i=1;i<=n;i++)
     84         for (int j=i+1;j<=n;j++)
     85         {
     86             len++;
     87             l[len].make(p[i],p[j]);
     88         }
     89     sort(l+1,l+1+len);
     90     l[0].k=l[len+1].k=-1e18; l[0].b=l[len+1].b=-1e18;
     91     {
     92         int j=0;
     93         for (int i=1;i<=len;i++) if (l[i]!=l[i-1]) l[++j]=l[i];
     94         len=j;
     95     }
     96     
     97     for (int i=1;i<=n;i++)
     98         for (int j=1;j<=len;j++)
     99             if ((neq(l[j].k,1e18) && equ(l[j].k*p[i].x+l[j].b,p[i].y))
    100             || (equ(l[j].k,1e18) && equ(p[i].x,l[j].b)))
    101                 vl[j].push_back(i),vp[i].push_back(j);
    102     
    103     for (int i=1;i<=n;i++)
    104         for (int j=0,to=vp[i].size();j<to;j++)
    105         {
    106             int u=vp[i][j];
    107             for (int k=0,too=vl[u].size();k<too;k++)
    108             {
    109                 int x=vl[u][k];
    110                 base[0].a[i][x]+=1.0/(to*too);
    111             }
    112         }
    113     
    114     for (int i=1;i<=17;i++) base[i]=base[i-1]*base[i-1];
    115     int lq=qread(),x,y;
    116     while (lq--)
    117     {
    118         x=qread(); y=qread(); y--;
    119         memset(f,0,sizeof(f)); f[x]=1;
    120         for (int i=0;i<=17;i++) if ((y>>i)&1) mul(f,base[i]);
    121         double ans=0;
    122         for (int i=1;i<=len;i++)
    123         {
    124             double tmp=0;
    125             for (int j=0,to=vl[i].size();j<to;j++) tmp+=f[vl[i][j]];
    126             ans=max(ans,tmp/vl[i].size());
    127         }
    128         cout<<ans<<endl;
    129     }
    130     return 0;
    131 }
    View Code
  • 相关阅读:
    Daily Scrum NO.4
    Daily Scrum NO.3
    Daily Scrum NO.2
    Daily Scrum NO.1
    Beta任务项录入
    M1事后分析报告
    wenbao与概率
    wenbao与组合数
    wenbao与高斯消元
    wenbao与链表
  • 原文地址:https://www.cnblogs.com/Blue233333/p/9189072.html
Copyright © 2011-2022 走看看