洛谷 U45568 賭神:決鬥
阿新 • • 發佈:2018-10-31
題目描述
\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
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
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,M≤50
- 對於另外20\%20%的資料,\sum_{i=1}^NA_i\le10^6,\sum_{j=1}^MB_j\le10^6∑i=1NAi≤106,∑j=1MBj≤106
- 對於100\%100%的資料,0<N,M\le2000,0<A_i,B_i\le10^90<N,M≤2000,0<Ai,Bi≤109
做法:
由於最多隻有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 }