几道期望题
Double PatiencePOJ - 2794
一个水题,但是我的状压被卡T了,记忆化搜索能过。。
1 //Achen
2 #include<algorithm>
3 #include<iostream>
4 #include<cstring>
5 #include<cstdlib>
6 #include<vector>
7 #include<cstdio>
8 #include<queue>
9 #include<cmath>
10 #include<set>
11 #define For(i,a,b) for(int i=(a);i<=(b);i++)
12 #define Rep(i,a,b) for(int i=(a);i>=(b);i--)
13 const int up=1953125;
14 typedef long long LL;
15 typedef double db;
16 using namespace std;
17 char s[15][10][10];
18 int power[20],vis[up+1];
19 db f[up+7];
20
21 template<typename T> void read(T &x) {
22 char ch=getchar(); x=0; T f=1;
23 while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
24 if(ch=='-') f=-1,ch=getchar();
25 for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f;
26 }
27
28 db dp(int u) {
29 if(vis[u]) return f[u];
30 vis[u]=1;
31 int a[10],cnt=0;
32 for(int i=1,t=u;i<=9;i++,t/=5) a[i]=t%5;
33 For(i,1,9)
34 For(j,i+1,9)
35 if(a[i]&&a[j]&&s[i][a[i]][0]==s[j][a[j]][0]) {
36 cnt++;
37 f[u]+=dp(u-power[j-1]-power[i-1]);
38 }
39 if(cnt) f[u]/=(db)cnt;
40 return f[u];
41 }
42
43 int main() {
44 power[0]=1;
45 For(i,1,9) power[i]=power[i-1]*5;
46 For(i,1,9)
47 For(j,1,4)
48 scanf("%s",s[i][j]);
49 f[0]=1.0;
50 printf("%.6f",dp(up-1));
51 return 0;
52 }
hdu3689Infinite monkey theorem
又是一道大水题,直接对询问串跑kmp,然后暴力dp转移
1 Time limit
2 1000 ms
3 Memory limit
4 32768 kB
5 OS
6 Windows
7 Source
8 2010 Asia Hangzhou Regional Contest
9
10 Result Time
11 Accepted 3 days ago
12 More...
13 Descriptions:
14
15 System Crawler 2018-04-18
16
17
18 Infinite monkey theorem
19 HDU - 3689
20 Preview:
21 All Copyright Reserved ©2018 Xu Han
22 Server Time: 2018-04-23 18:55:29 CST
23 #13571834 | achenachen's solution for [HDU-3689]
24 Status Accepted
25 Time 15ms
26 Memory 9668kB
27 Length 1547
28 Lang G++
29 Submitted 2018-04-20 10:15:50
30 Shared
31 RemoteRunId 24491353
32 Select Code
33
34 //Achen
35 #include<algorithm>
36 #include<iostream>
37 #include<cstring>
38 #include<cstdlib>
39 #include<vector>
40 #include<cstdio>
41 #include<queue>
42 #include<cmath>
43 #include<set>
44 #define For(i,a,b) for(int i=(a);i<=(b);i++)
45 #define Rep(i,a,b) for(int i=(a);i>=(b);i--)
46 typedef long long LL;
47 typedef double db;
48 using namespace std;
49 int n,m;
50 db p[30],f[1007][1007],tpp;
51 char s[10007];
52
53 template<typename T> void read(T &x) {
54 char ch=getchar(); x=0; T f=1;
55 while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
56 if(ch=='-') f=-1,ch=getchar();
57 for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f;
58 }
59
60 int nxt[1007];
61 void make_nxt(int n) {
62 for(int i=1,k=0;i<n;i++) {
63 while(k&&s[i]!=s[k]) k=nxt[k-1];
64 if(s[i]==s[k]) k++;
65 nxt[i]=k;
66 }
67 }
68
69 int main() {
70 #ifdef DEBUG
71 freopen(".in","r",stdin);
72 freopen(".out","w",stdout);
73 #endif
74 for(;;) {
75 read(n); read(m);
76 if(n==0&&m==0) break;
77 For(i,0,25) p[i]=0;
78 For(i,1,n) {
79 scanf("%s",s);
80 scanf("%lf",&tpp);
81 p[s[0]-'a']=tpp;
82 }
83 scanf("%s",s);
84 int len=strlen(s);
85 if(len>m) puts("0.00%");
86 else {
87 make_nxt(len);
88 memset(f,0,sizeof(f));
89 f[0][0]=1;
90 For(i,0,m-1)
91 For(j,0,len-1) if(f[i][j]!=0) {
92 For(k,0,25) if(p[k]!=0) {
93 int now=j;
94 while(now&&s[now]-'a'!=k) now=nxt[now-1];
95 if(s[now]-'a'==k) now++;
96 f[i+1][now]+=f[i][j]*p[k];
97 }
98 }
99 db ans=0;
100 For(i,len,m) ans+=f[i][len];
101 ans*=100;
102 printf("%.2lf",ans);
103 puts("%");
104 }
105 }
106 return 0;
107 }
把每个二进制位拆开考虑.
f[x]表示从x走到n得到1的概率
ans=(1<<i)*f[1]
高斯消元解出f即可
写的第一道高斯消元的题
1 //Achen
2 #include<algorithm>
3 #include<iostream>
4 #include<cstring>
5 #include<cstdlib>
6 #include<vector>
7 #include<cstdio>
8 #include<queue>
9 #include<cmath>
10 #include<set>
11 #define For(i,a,b) for(int i=(a);i<=(b);i++)
12 #define Rep(i,a,b) for(int i=(a);i>=(b);i--)
13 const int N=10007;
14 typedef long long LL;
15 typedef double db;
16 using namespace std;
17 int n,m,mxw;
18
19 template<typename T> void read(T &x) {
20 char ch=getchar(); x=0; T f=1;
21 while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
22 if(ch=='-') f=-1,ch=getchar();
23 for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f;
24 }
25
26 int ecnt,fir[N],nxt[N<<1],to[N<<1],val[N<<1];
27 void add(int u,int v,int w) {
28 nxt[++ecnt]=fir[u]; fir[u]=ecnt; to[ecnt]=v; val[ecnt]=w;
29 if(u!=v) {
30 nxt[++ecnt]=fir[v]; fir[v]=ecnt; to[ecnt]=u; val[ecnt]=w;
31 }
32 }
33
34 db g[107][107];
35 int gauss(int n) {
36 For(i,1,n) {
37 int now=i;
38 For(j,i+1,n) if(g[j][i]>g[now][i]) now=j;
39 if(now!=i) For(j,i,n+1) swap(g[i][j],g[now][j]);
40 if(!g[i][i]) return -1;
41 db t=g[i][i];
42 For(j,i,n+1) g[i][j]/=t;
43 For(j,i+1,n) if(g[j][i]) {
44 db t=g[j][i];
45 For(k,i,n+1) g[j][k]-=t*g[i][k];
46 }
47 }
48 Rep(i,n,1)
49 For(j,i+1,n) g[i][n+1]-=g[j][n+1]*g[i][j];
50 return 1;
51 }
52
53 db solve(int pos) {
54 memset(g,0,sizeof(g));
55 For(x,1,n-1) {
56 for(int i=fir[x];i;i=nxt[i]) {
57 g[x][x]++;
58 int y=to[i];
59 if(val[i]&(1<<pos)) {
60 g[x][y]++; g[x][n+1]++;
61 }
62 else g[x][y]--;
63 }
64 }
65 g[n][n]=1;
66 int rs=gauss(n);
67 if(rs==-1) return 0;
68 return g[1][n+1];
69 }
70
71 int main() {
72 #ifdef DEBUG
73 freopen(".in","r",stdin);
74 freopen(".out","w",stdout);
75 #endif
76 read(n); read(m);
77 For(i,1,m) {
78 int x,y,z;
79 read(x); read(y); read(z);
80 add(x,y,z); mxw=max(mxw,z);
81 }
82 db ans=0;
83 For(i,0,29) {
84 if((1<<i)>mxw) break;
85 db pp=solve(i);
86 ans+=pp*(1<<i);
87 }
88 printf("%.3lf\n",ans);
89 return 0;
90 }
91 /*
92 2 2
93 1 1 2
94 1 2 3
95
96 3 3
97 1 2 4
98 1 3 5
99 */
真正的大水题.
1 //Achen
2 #include<algorithm>
3 #include<iostream>
4 #include<cstring>
5 #include<cstdlib>
6 #include<vector>
7 #include<cstdio>
8 #include<queue>
9 #include<cmath>
10 #include<set>
11 #define For(i,a,b) for(int i=(a);i<=(b);i++)
12 #define Rep(i,a,b) for(int i=(a);i>=(b);i--)
13 typedef long long LL;
14 typedef double db;
15 using namespace std;
16 const int N=200007;
17 int n,m;
18
19 template<typename T> void read(T &x) {
20 char ch=getchar(); x=0; T f=1;
21 while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
22 if(ch=='-') f=-1,ch=getchar();
23 for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f;
24 }
25
26 int ecnt,fir[N],nxt[N],to[N],val[N],out[N],vis[N];
27 void add(int u,int v,int w) {
28 nxt[++ecnt]=fir[u]; fir[u]=ecnt; to[ecnt]=v; val[ecnt]=w; out[u]++;
29 }
30
31 db f[N];
32 void dfs(int x) {
33 if(vis[x]) return ;
34 vis[x]=1;
35 for(int i=fir[x];i;i=nxt[i]) {
36 int y=to[i];
37 dfs(y);
38 f[x]+=(f[y]+val[i]);
39 }
40 if(out[x]) f[x]=f[x]/(db)out[x];
41 }
42
43 int main() {
44 #ifdef DEBUG
45 freopen(".in","r",stdin);
46 freopen(".out","w",stdout);
47 #endif
48 read(n); read(m);
49 For(i,1,m) {
50 int u,v,w;
51 read(u); read(v); read(w);
52 add(u,v,w);
53 }
54 dfs(1);
55 printf("%.2lf\n",f[1]);
56 return 0;
57 }
f[x]表示x点冲到点的概率,如何转移都发现互相影响
那么考虑反着做,f[x]表示x点冲不上点的概率
g[x]表示只考虑以x为根的子树,x冲不上电的概率
p[x]表示x自己给自己冲上电的概率
q[x]表示x到父亲的边能用的概率
g[x]=(1-p[x])*∏(y is son of x)(g[y]+(1-g[y])*(1-p[y]));
一遍树dp求出g
对于根rt , f[rt]=g[rt]
从根往下依次计算每个点的f,相当于树dp换根,把父亲的f值除去我的贡献,父亲就变成了我的儿子.可以计算出我的f值
1 //Achen
2 #include<algorithm>
3 #include<iostream>
4 #include<cstring>
5 #include<cstdlib>
6 #include<vector>
7 #include<cstdio>
8 #include<queue>
9 #include<cmath>
10 #include<set>
11 #define For(i,a,b) for(int i=(a);i<=(b);i++)
12 #define Rep(i,a,b) for(int i=(a);i>=(b);i--)
13 const int N=1001000;
14 typedef long long LL;
15 typedef double db;
16 using namespace std;
17 int n,m;
18 db p[N];
19
20 template<typename T> void read(T &x) {
21 char ch=getchar(); x=0; T f=1;
22 while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
23 if(ch=='-') f=-1,ch=getchar();
24 for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f;
25 }
26
27 int ecnt,fir[N],nxt[N<<1],to[N<<1];
28 db val[N<<1];
29 void add(int u,int v,db w) {
30 nxt[++ecnt]=fir[u]; fir[u]=ecnt; to[ecnt]=v; val[ecnt]=w;
31 nxt[++ecnt]=fir[v]; fir[v]=ecnt; to[ecnt]=u; val[ecnt]=w;
32 }
33
34 db f[N],g[N],ans;
35 void dfs1(int x,int fa) {
36 g[x]=(1.0-p[x]);
37 for(int i=fir[x];i;i=nxt[i]) if(to[i]!=fa) {
38 int y=to[i];
39 dfs1(y,x);
40 g[x]*=(g[y]+(1.0-g[y])*(1.0-val[i]));
41 }
42 }
43
44 void dfs2(int x,int fa) {
45 ans+=(1.0-f[x]);
46 for(int i=fir[x];i;i=nxt[i]) if(to[i]!=fa) {
47 int y=to[i];
48 db tp=g[y]+(1.0-g[y])*(1.0-val[i]);
49 db ff=tp<1e-6?0:f[x]/tp;
50 f[y]=g[y]*(ff+(1.0-ff)*(1.0-val[i]));
51 dfs2(y,x);
52 }
53 }
54
55 int main() {
56 #ifdef DEBUG
57 freopen(".in","r",stdin);
58 freopen(".out","w",stdout);
59 #endif
60 read(n);
61 For(i,1,n-1) {
62 int u,v; db w;
63 read(u); read(v); read(w);
64 w/=100.0;
65 add(u,v,w);
66 }
67 For(i,1,n) { read(p[i]); p[i]/=100.0; }
68 dfs1(1,0);
69 f[1]=g[1];
70 dfs2(1,0);
71 printf("%.6lf\n",ans);
72 return 0;
73 }