洛谷 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 }

 

转载于:https://www.cnblogs.com/traveller-ly/p/9885448.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值