求助「luogu3706」[SDOI2017]硬币游戏

Posted Cupcake

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了求助「luogu3706」[SDOI2017]硬币游戏相关的知识,希望对你有一定的参考价值。

给题解跪辣!

这做法太神了。。

 

看到Accepted之前我一直不信这程序能AC。

因为方程系数的数量级是从10-1到10-91的!

用double储存跑高斯消元精度还不会爆炸!!

谁能告诉我是为什么

 1 #include<bits/stdc++.h>
 2 #define db double
 3 using namespace std;
 4 const int N=310,M=90010;
 5 const db eps=1e-10;
 6 int n,m;
 7 int ch[M][2],fail[M],v[M],dis[M],tot,pos[N];
 8 db a[N][N],p2[N];
 9 char s[N]; 
10 vector<int>bel[M];
11 void insert(char* str,int id){
12     int now=0;
13     for(int i=0;i<m;i++){
14         bel[now].push_back(id);
15         bool b=str[i]==H;
16         if(!ch[now][b]) ch[now][b]=++tot,dis[tot]=dis[now]+1;
17         now=ch[now][b];
18     }
19     v[now]=id,pos[id]=now;
20     return;
21 }
22 void build_ac(){
23     queue<int>q;
24     for(int i=0;i<=1;i++) if(ch[0][i]) q.push(ch[0][i]);
25     int x,nxt;
26     while(!q.empty()){
27         x=q.front();q.pop();
28         for(int i=0;i<=1;i++)if(ch[x][i]){
29             q.push(ch[x][i]);
30             nxt=fail[x];
31             while(nxt&&!ch[nxt][i]) nxt=fail[nxt];
32             fail[ch[x][i]]=ch[nxt][i];
33         }
34     }
35     return;
36 }
37 void gauss(){
38     for(int i=1;i<=n;i++){
39         int nxt=i;
40         for(int j=i+1;j<=n;j++)
41             if(fabs(a[j][i])>fabs(a[nxt][i])) nxt=j;
42         if(nxt!=i) for(int j=i;j<=n+1;j++) swap(a[i][j],a[nxt][j]);
43         for(int j=i+1;j<=n;j++){
44             db f=a[j][i]/a[i][i];
45             for(int k=i;k<=n+1;k++) a[j][k]-=a[i][k]*f;
46         }
47     }
48     for(int i=n;i>=1;i--){
49         a[i][n+1]/=a[i][i];
50         for(int j=i-1;j>=1;j--) a[j][n+1]-=a[j][i]*a[i][n+1];
51     }
52     return;
53 }
54 int main(){
55     scanf("%d%d",&n,&m);
56     p2[0]=1;
57     for(int i=1;i<=m;i++) p2[i]=p2[i-1]/2;
58     for(int i=1;i<=n;i++) a[i][n+1]=-p2[m];
59     for(int i=1;i<=n;i++){scanf("%s",s);insert(s,i);}
60     build_ac();
61     for(int i=1;i<=n;i++){
62         a[i][i]=1;
63         int now=fail[pos[i]];
64         while(now){
65             for(int j=0;j<bel[now].size();j++){
66                 int pre=bel[now][j];
67                 a[pre][i]+=p2[m-dis[now]];
68             }
69             now=fail[now];
70         }
71     }
72     for(int i=1;i<=n;i++) a[n+1][i]=1;
73     a[n+1][n+2]=1;
74     n++;
75     gauss();
76     for(int i=1;i<n;i++) printf("%.10lf\n",a[i][n+1]);
77     return 0;
78 }

 

以上是关于求助「luogu3706」[SDOI2017]硬币游戏的主要内容,如果未能解决你的问题,请参考以下文章

@loj - 2004@ 「SDOI2017」硬币游戏

Bzoj4820 [Sdoi2017]硬币游戏

BZOJ4820[Sdoi2017]硬币游戏 AC自动机+概率DP+高斯消元

[SDOI2017]硬币游戏

SDOI2017硬币游戏

[Luogu 3707] SDOI2017 相关分析