1. 程式人生 > >洛谷 U45568 賭神:決鬥

洛谷 U45568 賭神:決鬥

題目描述

\mathcal{tomoo}tomoo決定與\mathcal{CYJian}CYJian進行決鬥!

已知\mathcal{tomoo}tomoo有\mathcal{N}N張撲克牌,每張撲克牌有一個\mathcal{RP}RP值\mathcal{A_i}Ai\mathcal{CYJian}CYJian有\mathcal{M}M張撲克牌,每張撲克牌有一個\mathcal{RP}RP值\mathcal{B_i}Bi

\mathcal{CYJian}CYJian與\mathcal{tomoo}tomoo將會各自從他們的牌裡任意取一段連續區間的牌決鬥,誰的區間內的牌的\mathcal{RP}RP值的和更大,誰就贏了,請你幫忙求出\mathcal{tomoo}tomoo贏的概率。

輸入輸出格式

輸入格式:

 

  • 第一行22個正整數\mathcal{N,M}N,M
  • 第二行NN個正整數\mathcal{A_i}Ai
  • 第三行MM個正整數\mathcal{B_i}Bi

 

輸出格式:

 

一個數表示\mathcal{tomoo}tomoo獲勝的概率,如果答案可以表示成\frac{P}{Q}QP的形式,則輸出\frac{P}{Q}\%998244353QP%998244353(不懂的左轉P3811

 

輸入輸出樣例

輸入樣例#1:  複製
5 5
1 2 3 4 5
1 3 5 7 9
輸出樣例#1:  複製
754229067
輸入樣例#2:  複製
10 15
7 8 5 1 2 3 6 5 4 1 
52 10 5 6 3 2 1 4 5 8 7 4 5 6 3
輸出樣例#2:  複製
181952721
輸入樣例#3:  複製
1 1
5
5
輸出樣例#3:  複製
0
輸入樣例#4:  複製
5 5
1254125 36521421 25362142 12514221 25362142
857412252 36322411 2236232 1254112 36224125
輸出樣例#4:  複製
261761853
輸入樣例#5:  複製
2 2
2 4
2 5
輸出樣例#5:  複製
332748118

說明

樣例解釋

  • 樣例33:不管怎麼抽都是平均,勝率為00
  • 樣例55:共有99種方案,其中33次tomoo會贏,勝率為1/31/3

資料範圍

  • 對於20\%20%的資料,0<N,M\le500<N,M50
  • 對於另外20\%20%的資料,\sum_{i=1}^NA_i\le10^6,\sum_{j=1}^MB_j\le10^6i=1NAi106,j=1MBj106
  • 對於100\%100%的資料,0<N,M\le2000,0<A_i,B_i\le10^90<N,M2000,0<Ai,Bi109

做法:

由於最多隻有20002000個數,我們可以算出一個長度為N的數列,它共有(N+1)N/2個區間,也就是說最多隻會有2001000個區間和,所以我們對於每一個數列,用一個數組將每一個區間和儲存下來就好了。

然後將兩個陣列排序(其實排一個數組就行了),再列舉其中的一個數組,同時用尺取來統計答案。

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <iostream>
 4 #include <algorithm>
 5 #define N 4007
 6 #define LL long long
 7 #define mo 998244353
 8 using namespace std;
 9 int n,m,tot1,tot2,a[N],b[N],sum;
10 LL qa[N],qb[N];
11 LL suma[N*N],sumb[N*N];
12 
13 LL ksm(LL a,LL b){
14     LL q=1,base=a;
15     while(b){
16         if(b&1) q*=base,q%=mo;
17         base*=base;
18         base%=mo;
19         b>>=1;
20     }
21     return q;
22 }
23 
24 int main(){
25     scanf("%d%d",&n,&m);
26     for(int i=1;i<=n;i++) scanf("%d",&a[i]),qa[i]=qa[i-1]+a[i];
27     for(int i=1;i<=m;i++) scanf("%d",&b[i]),qb[i]=qb[i-1]+b[i];
28     for(int i=1;i<=n;i++){
29         for(int j=i;j<=n;j++)
30             suma[++tot1]=qa[j]-qa[i-1];
31     }
32     for(int i=1;i<=m;i++){
33         for(int j=i;j<=m;j++)
34             sumb[++tot2]=qb[j]-qb[i-1];
35     }
36     sort(suma+1,suma+tot1+1);
37     sort(sumb+1,sumb+tot2+1);
38     int j=0;
39     for(int i=1;i<=tot1;i++){
40         while(suma[i]>sumb[j+1]&&j+1<=tot2) j++;
41         sum+=j;
42         if (sum>mo) sum-=mo;
43     }
44     LL g=n*(n+1)/2;
45     g=g*m%mo*(m+1)%mo;
46     g=g*ksm(2,mo-2)%mo;    
47     printf("%lld",sum*ksm(g,mo-2)%mo);
48 }