傳送門
文章目錄
題意:
思路:
將矩陣中的數放到數組里排序,就是一個比較明顯的期望dpdpdp了。
定義f[i]f[i]f[i]表示從第iii個出發的期望得分,所以轉移方程也比較好寫了:f[i]=∑(f[j]+(x[i]?x[j])2+(y[i]?y[j])2)cntf[i]=\frac{\sum(f[j]+(x[i]-x[j])^2+(y[i]-y[j])^2)}{cnt}f[i]=cnt∑(f[j]+(x[i]?x[j])2+(y[i]?y[j])2)?
但是這樣有個問題,如果直接轉移的話那就是O(n2m2)O(n^2m^2)O(n2m2)的了,看到平方這些東西我們會本能的拆開,所以我們考慮化簡式子來進行O(1)O(1)O(1)轉移。
對于分母:∑f[j]+(x[i]2+y[i]2)?cnt+∑(x[j]2+y[j]2)?2?x[i]?∑x[j]?2?y[i]?∑y[j]\sum f[j]+(x[i]^2+y[i]^2)*cnt+\sum(x[j]^2+y[j]^2)-2*x[i]*\sum x[j]-2*y[i]* \sum y[j]∑f[j]+(x[i]2+y[i]2)?cnt+∑(x[j]2+y[j]2)?2?x[i]?∑x[j]?2?y[i]?∑y[j]
我們發現我們只需要維護∑f[j],∑(x[j]2+y[j]2),∑x[j],∑y[j]\sum f[j],\sum(x[j]^2+y[j]^2),\sum x[j],\sum y[j]∑f[j],∑(x[j]2+y[j]2),∑x[j],∑y[j]即可實現O(1)O(1)O(1)轉移了。
實現的時候需要等相同的值都算完了才能加上他們的貢獻,且由于每個點的x,yx,yx,y都不同,需要單獨計算,一開始以為一樣就在代碼的797979行鬼使神差的寫成了f[i]=f[i?1]f[i]=f[i-1]f[i]=f[i?1],真是老笨蛋啦。
#include<cstdio>
#include<iostream>
#include<string>
#include<cstring>
#include<map>
#include<cmath>
#include<cctype>
#include<vector>
#include<set>
#include<queue>
#include<algorithm>
#include<sstream>
#include<ctime>
#include<cstdlib>
#define X first
#define Y second
#define L (u<<1)
#define R (u<<1|1)
#define pb push_back
#define mk make_pair
#define Mid (tr[u].l+tr[u].r>>1)
#define Len(u) (tr[u].r-tr[u].l+1)
#define random(a,b) ((a)+rand()%((b)-(a)+1))
#define db puts("---")
using namespace std
;
typedef long long LL
;
typedef unsigned long long ULL
;
typedef pair
<int,int> PII
;const int N
=1000010,mod
=998244353,INF
=0x3f3f3f3f;
const double eps
=1e-6;int n
,m
,tot
;
LL f
[N
],pref
,prex
,prey
,prex2
,prey2
,pre
;
struct Node
{LL x
,y
,val
;bool operator < (const Node
&w
) const{return val
<w
.val
;}
}a
[N
];LL
qmi(LL a
,LL b
)
{LL ans
=1;while(b
){if(b
&1) ans
=ans
*a
%mod
;a
=a
*a
%mod
;b
>>=1;}return ans
%mod
;
}int main()
{
scanf("%d%d",&n
,&m
);for(int i
=1;i
<=n
;i
++) for(int j
=1;j
<=m
;j
++) { LL x
; scanf("%lld",&x
); a
[++tot
]={i
,j
,x
}; }sort(a
+1,a
+1+tot
);int cnt
=0; a
[0].val
=-1;for(int i
=2;i
<=tot
;i
++){if(a
[i
].val
!=a
[i
-1].val
){int pos
=i
-1,val
=a
[i
-1].val
;while(pos
>=1&&a
[pos
].val
==val
) (prex
+=a
[pos
].x
)%=mod
,(prey
+=a
[pos
].y
)%=mod
,(prex2
+=a
[pos
].x
*a
[pos
].x
)%=mod
,(prey2
+=a
[pos
].y
*a
[pos
].y
)%=mod
,(pre
+=f
[pos
])%=mod
,pos
--,cnt
++;f
[i
]=((pre
+(a
[i
].x
*a
[i
].x
+a
[i
].y
*a
[i
].y
)*cnt
+prex2
+prey2
-2*a
[i
].x
*prex
-2*a
[i
].y
*prey
)%mod
+mod
)%mod
*qmi(cnt
,mod
-2)%mod
;}else f
[i
]=((pre
+(a
[i
].x
*a
[i
].x
+a
[i
].y
*a
[i
].y
)*cnt
+prex2
+prey2
-2*a
[i
].x
*prex
-2*a
[i
].y
*prey
)%mod
+mod
)%mod
*qmi(cnt
,mod
-2)%mod
;}LL ans
=-1;int sx
,sy
; cin
>>sx
>>sy
;for(int i
=1;i
<=tot
;i
++) if(a
[i
].x
==sx
&&a
[i
].y
==sy
) { ans
=f
[i
]; break; }cout
<<ans
%mod
<<endl
;return 0;
}
總結
以上是生活随笔為你收集整理的CF1042E Vasya and Magic Matrix 期望dp + 推公式的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。