我是靠谱客的博主 动人冰棍,这篇文章主要介绍AGC 050 D题解AGC 050 D题解,现在分享给大家,希望可以做个参考。

AGC 050 D题解

比赛的时候想到了O(N^6)的做法没敢写

这题的数据范围非常迷惑,如果你O(N^6)的做法,请关闭这篇题解,自己尝试写出来,然后就可以AC了

4e9的运算量只跑了 780ms,是真的神奇

首先这题的dp样子比较显然(一眼dp题)

可以先预处理处一个数组 p i , j , k , l p_{i,j,k,l} pi,j,k,l表示当前是第j轮,有i个人玩这个游戏,在这之前已经有k个人胜利了,最后这i个人当中又有l个胜利的概率。

这个东西的转移比较简单,随便暴力转移也不会T。

然后后面的步骤更加简单,每一个人分开来计算。

d p i , l , r dp_{i,l,r} dpi,l,r表示当前到达这个钦定的人,前面还剩下l个,后面还剩下r个人,到达这部的概率的概率。

转移直接枚举上一维的 l ′ , r ′ l',r' l,r就行了。

所以这题的区分度主要在于你是否敢写

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
/* { ###################### # Author # # Gary # # 2020 # ###################### */ #include<bits/stdc++.h> #define rb(a,b,c) for(int a=b;a<=c;++a) #define rl(a,b,c) for(int a=b;a>=c;--a) #define LL long long #define IT iterator #define PB push_back #define II(a,b) make_pair(a,b) #define FIR first #define SEC second #define FREO freopen("check.out","w",stdout) #define rep(a,b) for(int a=0;a<b;++a) #define SRAND mt19937 rng(chrono::steady_clock::now().time_since_epoch().count()) #define random(a) rng()%a #define ALL(a) a.begin(),a.end() #define POB pop_back #define ff fflush(stdout) #define fastio ios::sync_with_stdio(false) #define check_min(a,b) a=min(a,b) #define check_max(a,b) a=max(a,b) using namespace std; //inline int read(){ // int x=0; // char ch=getchar(); // while(ch<'0'||ch>'9'){ // ch=getchar(); // } // while(ch>='0'&&ch<='9'){ // x=(x<<1)+(x<<3)+(ch^48); // ch=getchar(); // } // return x; //} const int INF=0x3f3f3f3f; typedef pair<int,int> mp; /*} */ const int MOD=998244353; LL quick(LL A,LL B){ if(B==0) return 1; LL tmp=quick(A,B>>1); tmp*=tmp; tmp%=MOD; if(B&1) tmp*=A,tmp%=MOD; return tmp; } int invm; int n,m; int p[43][43][43][43]; int dp[43][43][43]; int good[43][43][43]; /* dp[i][j][l][m]=p[i-1][j][l]*p[n-i][j-1][m] */ int main(){ scanf("%d%d",&n,&m); invm=quick(m,MOD-2); rb(i,0,n) p[i][0][0][0]=1; rb(i,1,m+1) rb(j,i-1,m+1) p[0][i][j][0]=1; rb(i,1,n){ rb(j,1,m+1){//now rb(k,j-1,m+1){ rb(l,0,i){ if(l&&(m-(j-1))>=(m-k-(l-1))){ p[i][j][k][l]+=1ll*p[i-1][j][k][l-1]*(m-k-(l-1))%MOD*quick(m-(j-1),MOD-2)%MOD; } if(m-(j-1)>=(k+l-(j-1))){ p[i][j][k][l]+=1ll*p[i-1][j][k][l]*(k+l-(j-1))%MOD*quick(m-(j-1),MOD-2)%MOD; } p[i][j][k][l]%=MOD; } } } } rb(now,1,n){ memset(good,0,sizeof(good)); memset(dp,0,sizeof(dp)); int rest=0; dp[0][now-1][n-now]=1; rb(i,1,m){ rb(l,0,now-1){ rb(r,0,n-now){ rb(j,0,(now-1)-l){ rb(k,0,(n-now)-r){ dp[i][l][r]+=1ll*dp[i-1][l+j][r+k]*(1-good[i-1][l+j][r+k]+MOD)%MOD*p[r+k][i-1][(n-1-(l+j)-(r+k))][k]%MOD*p[l+j][i][n-1-(l+j)-r][j]%MOD; dp[i][l][r]%=MOD; } } int res=m-(n-1-l-r); good[i][l][r]=res*quick(m-(i-1),MOD-2)%MOD; rest+=1ll*dp[i][l][r]*good[i][l][r]%MOD; rest%=MOD; } } } printf("%dn",rest); } return 0; } /* 4 2 1 374341633 748683265 873463809 */

最后

以上就是动人冰棍最近收集整理的关于AGC 050 D题解AGC 050 D题解的全部内容,更多相关AGC内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(66)

评论列表共有 0 条评论

立即
投稿
返回
顶部