結果
| 問題 | No.1239 Multiplication -2 |
| コンテスト | |
| ユーザー |
uni_python
|
| 提出日時 | 2020-09-26 16:03:04 |
| 言語 | PyPy3 (7.3.15) |
| 結果 |
AC
|
| 実行時間 | 344 ms / 2,000 ms |
| コード長 | 3,008 bytes |
| 記録 | |
| コンパイル時間 | 153 ms |
| コンパイル使用メモリ | 82,440 KB |
| 実行使用メモリ | 119,600 KB |
| 最終ジャッジ日時 | 2024-06-29 03:29:31 |
| 合計ジャッジ時間 | 6,941 ms |
|
ジャッジサーバーID (参考情報) |
judge1 / judge5 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 3 |
| other | AC * 34 |
ソースコード
import sys
input=sys.stdin.readline
def I(): return int(input())
def MI(): return map(int, input().split())
def LI(): return list(map(int, input().split()))
"""
絶対値が2のところを起点に,前後の「絶対値が1以外である点」までを見る
此の幅を左A,右B個とする
左にa個,右にb個つなげられるかはは,その中に含まれる-1の個数次第.
此の時の期待値について考える,
a個の各両端の境界a+1個
b個の各両端の境界b+1個
は確定,あとは自由なので
2^((N-1)-((a+1)+(b+1)))
(ただし,a個,b個取った先が端ならa+1がaになったりするので注意かも?)
左右の組み合わせを一々考えるとO(N^2)でダメだが,それぞれ積が1.-1になる数を数えておいてあとでまとめる
左から見てa個使って1になるなら,他のところがフリー
"""
def main():
import bisect
mod=998244353
N=I()
A=LI()
POW=[1]
for i in range(N+3):
aaa=POW[-1]
POW.append((aaa*2)%mod)
inf=10**6
abs2=[]
abs_n1=[-1]
for i in range(N):
a=abs(A[i])
if a==2:
abs2.append(i)
if a!=1:
abs_n1.append(i)
abs_n1.append(N)
N2=len(abs_n1)
# 1,-1からなる数列を右から見ていき,積が1になる個数と-1になる個数をカウント
# Rが配列で,iiが今見ている2の位置
def count(R,ii):
NR=len(R)
M=N-1-ii-1#2のすぐ右においた際にフリーな場所の個数
# print(R,M)
if M==-1:# 端点
return 1,0
p1=POW[M]#2のすぐ右側を区切った場合,残りの箇所がフリー
m1=0
now=1
for i in range(NR):
a=R[i]
now*=a
M-=1
if M==-1:
M=0
# print(i,POW[M],"*")
if now>0:
p1+=POW[M]
p1%=mod
else:
m1+=POW[M]
m1%=mod
# print(ii,p1,m1)
return p1,m1
ans=0
for i in range(N):
a=A[i]
if abs(a)==2:
num=bisect.bisect_left(abs_n1,i)-1
left=abs_n1[num]
L=A[left+1:i]
lp1,lm1=count(L[::-1],N-i-1)
num2=bisect.bisect_left(abs_n1,i)+1
right=abs_n1[num2]
R=A[i+1:right]
rp1,rm1=count(R,i)
if a<0:#aが負なら,左右のpmは一致して欲しい
temp=lp1*rp1 + lm1*rm1
else:#aが正なら,左右のpmは不一致して欲しい
temp=lp1*rm1 + lm1*rp1
# print(i,temp)
# print()
ans+=temp
ans%=mod
aaa=pow(2,N-1,mod)
ans=ans*pow(aaa,mod-2,mod)
print(ans%mod)
main()
uni_python