6
5

More than 1 year has passed since last update.

AtCoder 最速で緑になる 基礎・典型50問詳細解説 コピペ用コード

Last updated at Posted at 2022-08-20

本記事は拙著『AtCoder 最速で緑になる 基礎・典型50問詳細解説』のコピペ用コード集ですです。
値段:100円(Kindle Unlimited対象)
【kindle】
https://www.amazon.co.jp/dp/B0BBB7RKTP

【booth(pdf)】
https://booth.pm/ja/items/4102300

冒頭5問をサンプルとして無料公開しています。
https://qiita.com/sano192/items/6361ed72106cb6dd5843

1 入力と出力 ABC205 A Dif:6

提出
# 入力の受け取り
A,B=map(int, input().split())

# A×(1/100)×Bを出力
print(A*(1/100)*B)

2 条件分岐1 ABC219 A Dif:6

提出
# 入力の受け取り
X=int(input())

# 初級の場合
if 0<=X<40:
    # 40-Xを出力
    print(40-X)
# 中級の場合
elif 40<=X<70:
    # 70-Xを出力
    print(70-X)
# 上級の場合
elif 70<=X<90:
    # 90-Xを出力
    print(90-X)
# エキスパートの場合
else:
    # "expert"を出力
    print("expert")

3 関数 ABC234 A Dif:7

提出
# 入力の受け取り
t=int(input())

# 関数の定義
# 引数;x 返り値:x^2+2x+3
def f(x):
    return x**2+2*x+3

# 答えの計算
ans=f(f(f(t)+t)+f(f(t)))

# 答えの出力
print(ans)

4 for文 ABC204 B Dif:9

提出
# 入力の受け取り
N=int(input())
A=list(map(int, input().split()))

# 答え
ans=0

# i=0~N-1まで
for i in range(N):
    # A[i]が10より大きければ
    if 10<A[i]:
        # A[i]-10をansにプラスする
        ans+=A[i]-10

# 答えの出力
print(ans)
別解
# 入力の受け取り
N=int(input())
A=list(map(int, input().split()))

# 答えの格納用変数
ans=0

# xへAの値を順に入れる
for x in A:
    # 0と(x-10)の大きい方を足す
    ans+=max(0,x-10)

# 答えの出力
print(ans)

5 文字列操作 ABC232 A Dif:9

提出
# 入力の受け取り
S=input()

# Sの0文字目と2文字目を整数へ変換
S0=int(S[0])
S2=int(S[2])

# 掛け算して出力
print(S0*S2)

6 文字コード変換 ABC218 B Dif:14

提出
# 入力の受け取り
P=list(map(int, input().split()))

# 答えを格納する変数
ans=""

# i=0~25
for i in range(26):
    # 文字コード「P[i]+96」の文字をansの末尾へ追加
    ans+=chr(P[i]+96)

# 答えを出力
print(ans)
別解
# 入力の受け取り
P=list(map(int, input().split()))

def convert(x):
    if x==1:return "a"
    if x==2:return "b"
    if x==3:return "c"
    if x==4:return "d"
    if x==5:return "e"
    if x==6:return "f"
    if x==7:return "g"
    if x==8:return "h"
    if x==9:return "i"
    if x==10:return "j"
    if x==11:return "k"
    if x==12:return "l"
    if x==13:return "m"
    if x==14:return "n"
    if x==15:return "o"
    if x==16:return "p"
    if x==17:return "q"
    if x==18:return "r"
    if x==19:return "s"
    if x==20:return "t"
    if x==21:return "u"
    if x==22:return "v"
    if x==23:return "w"
    if x==24:return "x"
    if x==25:return "y"
    if x==26:return "z"

ans=""

# i=0~25
for i in range(26):
    # P[i]を変換してansの末尾へ追加
    ans+=convert(P[i])

# 答えを出力
print(ans)

7 リスト操作 ABC241 A Dif:15

提出
# 入力の受け取り
a=list(map(int,input().split()))

# 最初に画面に表示されているのは「0」
k=0

# ボタンを押す
k=a[k]

# ボタンを押す
k=a[k]

# ボタンを押す
k=a[k]

# 答えを出力
print(k)

8 set ABC240 B Dif:19

提出
# 入力の受け取り
N=int(input())
a=list(map(int,input().split()))

# リスト→セットへ変換
aSet=set(a)

# 長さを出力
print(len(aSet))

9 図形 ABC246 A Dif:28

提出
# 入力の受け取り
x1,y1=map(int,input().split())
x2,y2=map(int,input().split())
x3,y3=map(int,input().split())

# x1=x2の場合
if x1==x2:
    x4=x3
# x2=x3の場合
elif x2==x3:
    x4=x1
# x3=x1の場合
elif x3==x1:
    x4=x2

# y1=y2の場合
if y1==y2:
    y4=y3
# y2=y3の場合
elif y2==y3:
    y4=y1
# y3=y1の場合
elif y3==y1:
    y4=y2

# 答えの出力
print(x4,y4)

10 二次元配列、ソート1 ABC201 B Dif:32

提出
# 入力の受け取り
N=int(input())

# 山の高さ、名前を格納するリスト
Mountains=[]

# N回
for i in range(N):
    # 入力の受け取り
    S,T=map(str, input().split())
    # Tを整数へ変換
    T=int(T)
    # T,Sの順に格納
    Mountains.append([T,S])

# 大きい順に並び替え
Mountains.sort(reverse=True)

# 1番目のリストの、1番目の要素を出力
print(Mountains[1][1])

11 二重ループ ABC234 B Dif:46

提出
# 入力の受け取り
N=int(input())

# 座標の格納用
x=[]
y=[]

# i=0~(N-1)
for i in range(N):
    # 入力の受け取り
    xi,yi=map(int,input().split())
    # 座標の格納
    x.append(xi)
    y.append(yi)

# mathのインポート
import math

# 答え
ans=0

# i=0~(N-1)
for i in range(N):
    # j=(i+1)~(N-1)
    for j in range(i+1,N):
        # 距離の計算
        length=math.sqrt((x[i]-x[j])**2+(y[i]-y[j])**2)
        # そこまでの値より大きければ更新
        ans=max(ans,length)

# 答えの出力
print(ans)

12 条件分岐2 ABC205 C Dif:63

提出
# 入力の受け取り
A,B,C=map(int, input().split())

# C:偶数
if C%2==0:
    # A:0以上(+)
    if 0<=A:
        # B:0以上(+)
        if 0<=B:
            # |A|<|B|
            if abs(A)<abs(B):
                # 「<」を出力
                print("<")
            # |A|=|B|
            if abs(A)==abs(B):
                # 「=」を出力
                print("=")
            # |A|>|B|
            if abs(A)>abs(B):
                # 「>」を出力
                print(">")
        # B:0未満(-)
        if B<0:
            # |A|<|B|
            if abs(A)<abs(B):
                # 「<」を出力
                print("<")
            # |A|=|B|
            if abs(A)==abs(B):
                # 「=」を出力
                print("=")
            # |A|>|B|
            if abs(A)>abs(B):
                # 「>」を出力
                print(">")

    # A:0未満(-)
    if A<0:
        # B:0以上(+)
        if 0<=B:
            # |A|<|B|
            if abs(A)<abs(B):
                # 「<」を出力
                print("<")
            # |A|=|B|
            if abs(A)==abs(B):
                # 「=」を出力
                print("=")
            # |A|>|B|
            if abs(A)>abs(B):
                # 「>」を出力
                print(">")
        # B:0未満(-)
        if B<0:
            # |A|<|B|
            if abs(A)<abs(B):
                # 「<」を出力
                print("<")
            # |A|=|B|
            if abs(A)==abs(B):
                # 「=」を出力
                print("=")
            # |A|>|B|
            if abs(A)>abs(B):
                # 「>」を出力
                print(">")

# C:奇数
if C%2==1:
    # A:0以上(+)
    if 0<=A:
        # B:0以上(+)
        if 0<=B:
            # |A|<|B|
            if abs(A)<abs(B):
                # 「<」を出力
                print("<")
            # |A|=|B|
            if abs(A)==abs(B):
                # 「=」を出力
                print("=")
            # |A|>|B|
            if abs(A)>abs(B):
                # 「>」を出力
                print(">")
        # B:0未満(-)
        if B<0:
            # |A|<|B|
            if abs(A)<abs(B):
                # 「>」を出力
                print(">")
            # |A|=|B|
            if abs(A)==abs(B):
                # 「>」を出力
                print(">")
            # |A|>|B|
            if abs(A)>abs(B):
                # 「>」を出力
                print(">")

    # A:0未満(-)
    if A<0:
        # B:0以上(+)
        if 0<=B:
            # |A|<|B|
            if abs(A)<abs(B):
                # 「<」を出力
                print("<")
            # |A|=|B|
            if abs(A)==abs(B):
                # 「<」を出力
                print("<")
            # |A|>|B|
            if abs(A)>abs(B):
                # 「<」を出力
                print("<")
        # B:0未満(-)
        if B<0:
            # |A|<|B|
            if abs(A)<abs(B):
                # 「>」を出力
                print(">")
            # |A|=|B|
            if abs(A)==abs(B):
                # 「=」を出力
                print("=")
            # |A|>|B|
            if abs(A)>abs(B):
                # 「<」を出力
                print("<")
別解
A,B,C=map(int, input().split())

if C%2==0:
    if abs(A)<abs(B):print("<")
    elif abs(A)==abs(B):print("=")
    else:print(">")
else:
    if 0<=A:
        if 0<=B:
            if abs(A)<abs(B):print("<")
            elif abs(A)==abs(B):print("=")
            else:print(">")
        else:print(">")
    else:
        if 0<=B:print("<")
        else:
            if abs(A)<abs(B):print(">")
            elif abs(A)==abs(B):print("=")
            else:print("<")

13 周期性 ABC220 C Dif:119

提出
# 入力の受け取り
N=int(input())
A=list(map(int, input().split()))
X=int(input())

# Aの合計
Asum=sum(A)

# 必要なAの数:X//(Aの合計)
quo=X//Asum

# 項数(k):(Aの個数)×(Aの要素数)
k=N*quo

# 合計(Bsum):(Aの個数)×(Aの合計)
Bsum=Asum*quo

# Xを超えるまでAの要素を順に足していく
# i=0~(N-1)まで
for i in range(N):
    # 合計に+A[i]
    Bsum+=A[i]
    # 項数に+1
    k+=1
    # X<合計になったら
    if X<Bsum:
        # 答えを出力
        print(k)
        # 終了
        exit()

14 逆順操作 ABC216 C Dif:145

提出
# 入力の受け取り
N=int(input())

# 答え(最初は空)
ans=""

# Nが0より大きい間
while 0<N:
    # Nが偶数なら
    if N%2==0:
        # ansの左端にBを追加
        ans="B"+ans
        # 2で割る
        N//=2
    # それ以外(Nが奇数なら)
    else:
        # ansの左端にAを追加
        ans="A"+ans
        # 1を引く
        N-=1

# 答えを出力
print(ans)

15 貪欲法 ABC229 C Dif:165

提出
# 入力の受け取り
N,W=map(int,input().split())

# チーズの情報
Cheese=[]

# N回
for i in range(N):
    # 入力の受け取り
    A,B=map(int,input().split())
    # 情報の格納
    Cheese.append([A,B])

# 美味しさの大きい順にソート
Cheese.sort(reverse=True)

# 答え
ans=0

# i=0~(N-1)まで
for i in range(N):
    # i種類目のチーズの美味しさ
    Delicious=Cheese[i][0]
    # i種類目のチーズの重さ
    Weight=Cheese[i][1]

    # 重さ≤Wなら
    if Weight<=W:
        # 全部載せる
        ans+=Delicious*Weight
        # 載せられる残りの重さ
        W-=Weight
    # そうでないなら(W<重さなら)
    else:
        # W[g]分載せる
        ans+=Delicious*W
        # これ以上載せられないからforを抜ける
        break

# 答えの出力
print(ans)

16 インタラクティブ ABC244 C Dif:165

提出
# 入力の受け取り
N=int(input())

# すでに使った数の記録
Used=[False]*(2*N+2)

# 最初は「1」を出力
print(1)

# 「1」は使用済み
Used[1]=True

# N回
for i in range(N+1):
    # 青木くんの入力を受け取り
    x=int(input())
    # 「x」は使った
    Used[x]=True

    # x=「0」の場合
    if x==0:
        # 終了
        exit()

    # k=1~(2k+1)
    for k in range(1,2*N+2):
        # まだ使っていないなら
        if Used[k]==False:
            # 「k」を出力
            print(k)
            # 「k」は使った
            Used[k]=True
            # forループを抜ける
            break

17 連想配列1 ABC206 C Dif:171

提出
# 入力の受け取り
N=int(input())
A=list(map(int, input().split()))

# defaultdictのインポート
from collections import defaultdict

# 要素の出現回数を数える連想配列countを用意
count=defaultdict(int)

# Aのそれぞれの要素(a)について
for i in range(N):
    # 出現回数を+1
    count[A[i]]+=1

# 全組み合わせ=NC2=N*(N-1)//2
ans=N*(N-1)//2

# countの値(x)それぞれについて
for x in count.values():
    # Ai=Ajとなる組の数x*(x-1)//2を引く
    ans-=x*(x-1)//2

# 答えの出力
print(ans)

18 itertools ABC215 C Dif:178

提出
# 入力の受け取り(Kも文字列として)
S,K=map(str,input().split())

# Kを整数に変換
K=int(K)

# 作れる文字を格納するセット(リストだと重複するものも入ってしまうためセットを使う)
Sset=set()

# itertoolsをインポート
import itertools
# p=(0,1,2),(0,2,1),(1,0,2),(1,2,0),...
for p in itertools.permutations(range(len(S))):
    # 作った文字列を記録する変数
    Stmp=""
    # pを使って文字を作成
    # 例:p=(2,0,1)ならStmp=Sの2文字目+Sの0文字目+Sの1文字目
    for i in p:
        Stmp+=S[i]
    # できた文字をSsetに格納(setへの追加はappendではなくaddであることに注意)
    Sset.add(Stmp)

# ソートするためにリストへ変換
Slist=list(Sset)

# 辞書順にソート
Slist.sort()

# K-1番目の要素を出力
print(Slist[K-1])

19 二分探索1 ABC231 C Dif:194

提出
# 入力の受け取り
N,Q=map(int,input().split())
A=list(map(int,input().split()))

# Aをソート
A.sort()

# 二分探索
# 引数:x 返り値:「身長がx以上の中で最も小さい人は何番目か」
def Nibutan(x):
    # 左端
    l=0
    # 右端
    r=N-1

    # 1<右端-左端の間
    while 1<r-l:
        # 中央
        c=(l+r)//2

        # A[c]<xならば(条件を満たさない場合)
        if A[c]<x:
            # 左端を中央へ更新
            l=c
        # そうでなければ(x≤A[c] 条件を満たす場合)
        else:
            # 右端を中央へ更新
            r=c
       
    # 右端を返す
    return r

# Q回
for i in range(Q):
    # 入力の受け取り
    x=int(input())

    # xがAの中で最小の要素以下である場合
    if x<=A[0]:
        # N人
        print(N)
    # xがAの中で最大の要素より大きい場合
    elif A[N-1]<x:
        print(0)
    # それ以外
    else:
        # 答えの出力
        print(N-Nibutan(x))
別解
# 入力の受け取り
N,Q=map(int,input().split())
A=list(map(int,input().split()))

# Aをソート
A.sort()

# クエリの記録
query=[]

# Q回
for i in range(Q):
    # 入力の受け取り
    x=int(input())
    # [x,i番目のクエリ]と記録
    query.append([x,i])

# クエリをxの小さい順にソート
query.sort()
# 答えの格納用リスト
Ans=[0]*Q

# インデックス:初期値は0
k=0
# 各クエリについて
for x,i in query:
 
    # A[k]<xである限り
    while k<N and A[k]<x:
        # kを先に進める
        k+=1

    # A[k]はx以上
    # i番目のクエリの答えを記録
    Ans[i]=N-k

# 答えの出力
for a in Ans:print(a)

20 ソート2 ABC209 C Dif:285

提出
# 入力の受け取り
N=int(input())
C=list(map(int, input().split()))

# mod=10^9+7と定義
mod=10**9+7

# Cをソート
C.sort()

# 答えを格納する変数
ans=1

# i=0~(N-1)まで
for i in range(N):
    # もしC[i]-i=0ならば
    if C[i]-i==0:
        # 0を出力
        print(0)
        # 終了
        exit()

    # ansにC[i]-iをかける
    ans*=C[i]-i
    # 余りを取る
    ans%=mod

# 答えを出力
print(ans)

21 シミュレーション1 ABC214 C Dif:319

提出
# 入力の受け取り
N=int(input())
S=list(map(int, input().split()))
T=list(map(int, input().split()))

# i番目のすぬけ君が初めて宝石をもらう時間
# 初期値は大きい数
time=[10**15]*N

# 1週目
for i in range(N):
    # 次のすぬけ君の番号。i=N-1のとき、次のすぬけ君の番号=Nではなく=0とするためNで割った余りを取る
    next=(i+1)%N
    # 高橋君からもらうのが早いか、隣のすぬけ君からもらうのが早いか
    time[next]=min(T[next],time[i]+S[i])

# 2周目
for i in range(N):
    next=(i+1)%N
    # 1周目で計算した時間が早いか、隣のすぬけ君からもらうのが早いか
    time[next]=min(time[next],time[i]+S[i])

# 答えの出力
for i in range(N):
  print(time[i])

22 bit全探索 ABC221 C Dif:379

提出
# 入力の受け取り(文字列)
N=input()

# 答え 初期値は0
ans=0

# bitnum=(000000),(000001),(000010),(000011),...,(111111)まで
for bitnum in range(1<<len(N)):
    # グループA,Bを用意
    A=[]
    B=[]

    # shift=0~(Nの桁数-1)まで
    for shift in range(len(N)):
    # bitnumのshift桁目が「0」か「1」か確認
    # 右にshift分シフト演算して「1」とアンド演算
        # 0ならば
        if bitnum>>shift & 1==0:
            # グループAへ追加
            A.append(N[shift])
        # 1ならば
        else:
            # グループBへ追加
            B.append(N[shift])

    # グループAまたはグループBが空なら
    if A==[] or B==[]:
        # 次のbitnum
        continue

    # 大きい順に並び替え
    A.sort(reverse=True)
    B.sort(reverse=True)

    # A,Bを結合
    A_join="".join(A)
    B_join="".join(B)
 
    # 整数にして掛け算
    tmp_ans=int(A_join)*int(B_join)
 
    # ansよりtmp_ansが大きかったらansを更新
    ans=max(ans,tmp_ans)

# 答えの出力
print(ans)

23 区間の処理 ABC207 C Dif:397

提出
# 入力の受け取り
N=int(input())

# 区間の格納リスト
section=[]

# N回
for i in range(N):
    # 入力の受け取り
    t,l,r=map(int, input().split())
    # t=1の場合
    if t==1:
        # 区間[l,r]を追加
        section.append([l,r])
    # t=2の場合
    elif t==2:
        # 区間[l,r-0.1]を追加
        section.append([l,r-0.1])
    # t=3の場合
    elif t==3:
        # 区間[l+0.1,r]を追加
        section.append([l+0.1,r])
    # t=4の場合
    elif t==4:
        # 区間[l+0.1,r-0.1]を追加
        section.append([l+0.1,r-0.1])

# 答えの格納用変数
ans=0

# i=0~(N-1)まで
for i in range(N):
    # j=(i+1)~(N-1)まで
    for j in range(i+1,N):
        # 区間iの左端
        il=section[i][0]
        # 区間iの右端
        ir=section[i][1]
        # 区間jの左端
        jl=section[j][0]
        # 区間jの右端
        jr=section[j][1]

        # (区間iの左端)≤(区間jの左端)≤(区間iの右端)
        if il<=jl<=ir:
            # 答えにカウント
            ans+=1
        # (区間iの左端)≤(区間jの右端)≤(区間iの右端)
        elif il<=jr<=ir:
            # 答えにカウント
            ans+=1        
        # (区間jの左端)≤(区間iの左端)≤(区間jの右端)
        elif jl<=il<=jr:
            # 答えにカウント
            ans+=1        
        # (区間jの左端)≤(区間iの右端)≤(区間jの右端)
        elif jl<=ir<=jr:
            # 答えにカウント
            ans+=1

# 答えの出力
print(ans)
別解
# 入力の受け取り
N=int(input())

# 区間の格納リスト
section=[]

# N回
for i in range(N):
    # 入力の受け取り
    t,l,r=map(int, input().split())
    # t=1の場合
    if t==1:section.append([l,r])
    # t=2の場合
    elif t==2:section.append([l,r-0.1])
    # t=3の場合
    elif t==3:section.append([l+0.1,r])
    # t=4の場合
    else:section.append([l+0.1,r-0.1])

# 答えの格納用変数
ans=0

# i=0~(N-1)まで
for i in range(N):
    # j=(i+1)~(N-1)まで
    for j in range(i+1,N):
        # 区間i,jの右端,左端
        il,ir=section[i]
        jl,jr=section[j]
      
        # max(区間iの左端,区間jの左端)≤min(区間iの右端,区間jの右端)ならば
        # 答えにカウント
        if max(il,jl)<=min(ir,jr):ans+=1

# 答えの出力
print(ans)

24 座標圧縮 ABC213 C Dif:481

提出
# 入力の受け取り
H,W,N=map(int, input().split())

# カードの[行番号,列番号]を受け取るリスト
cards=[]
# 行番号だけ受け取るリスト
Gyou=[]
# 列番号だけ受け取るリスト
Retu=[]

# N回
for i in range(N):
    # 入力の受け取り
    A,B=map(int, input().split())
    # カードの[行番号,列番号]を受け取り
    cards.append([A,B])
    # 行番号を受け取り
    Gyou.append(A)
    # 列番号を受け取り
    Retu.append(B)

# 重複の削除(setにする)
Gyou=set(Gyou)
# リストに直す(setはソートできない)
Gyou=list(Gyou)
# ソートする
Gyou.sort()

# 変換先を記録する連想配列
GyouConvert=dict()

# 重複削除後の行の個数分
for i in range(len(Gyou)):
    # もとの行番号→インデックス番号+1と変換できるように記録(小さい方から何番目にあるか?)
    GyouConvert[Gyou[i]]=i+1

#列も同じことをする
Retu=set(Retu)
Retu=list(Retu)
Retu.sort()

RetuConvert=dict()

for i in range(len(Retu)):
    RetuConvert[Retu[i]]=i+1

# それぞれのカードについて行、列番号を変換して出力
for Gyou,Retu in cards:
    # 行番号の変換
    AnsGyou=GyouConvert[Gyou]
    # 列番号の変換
    AnsRetu=RetuConvert[Retu]
    # 答えを出力する
    print(AnsGyou,AnsRetu)

25 heap ABC234 D Dif:503

提出
# 入力の受け取り
N,K=map(int,input().split())
P=list(map(int,input().split()))

# heapqのインポート
import heapq

# (1)heap queueを用意する
que=[]
 
# (2)P1~PKをheap queueへ入れる
for i in range(K):
    heapq.heappush(que,P[i])

# (3)heap queueの最小値を出力する
print(que[0])

# i=K~(N-1)
for i in range(K,N):
    # (4)heap queueから最小値を取り出す
    x=heapq.heappop(que)
    # (5)(heap queueの最小値)とPiのうち大きい方をheap queueへ戻す
    heapq.heappush(que,max(x,P[i]))
    # (6)(heap queueの最小値)を出力する
    print(que[0])
    # (7)次のiへ((4)へ戻る)

26 deque ABC237 D Dif:544

提出
# 入力の受け取り
N=int(input())
S=input()

# deque のインポート
from collections import deque

# キューを用意
que=deque()

# Nを追加
que.append(N)

# i=(N-1)~0 -1ずつ
for i in range(N-1,-1,-1):
    # Sのi文字目が「R」
    if S[i]=="R":
        # 先頭(左端)へ「i」を追加
        que.appendleft(i)
    # そうでない場合(Sのi文字目が「L」)
    else:
        # 末端(右端)へ「i」を追加
        que.append(i)  

# 答えの出力
# ([]がいらない場合は先頭に「*」をつける)
print(*que)

27 DP1 ABC211 C Dif:559

提出
# 入力の受け取り
S=input()
# 文字数=N
N=len(S)

# Sの0文字目を?にする
S="?"+S
# T=?chokudai(?は0文字目)
T="?chokudai"

# 余りの定義
mod=10**9+7

# (1)表を作る
dp=[[0]*9 for i in range(N+1)]
 
# (2)すぐにわかるところを埋める
# i=0~N
for i in range(N+1):
    # k=0
    dp[i][0]=1

# (3)表の小さい方から答えにたどり着くまで埋める
# Sのi文字目までを使う
for i in range(1,N+1):
    # chokudaiのk文字目までを作る
    for k in range(1,9):
        # 1≤i≤N,1≤k≤8,Sのi文字目=chokudaiのk文字目の場合
        if S[i]==T[k]:
            # dp[i-1][k]:Sの(i-1)文字目までを使ってchokudaiのk文字目を作る場合(Sのi文字目を使わない)
            # dp[i-1][k-1]:Sの(i-1)文字目までを使ってchokudaiの(k-1)文字目を作る場合(Sのi文字目を使う)
            dp[i][k]=dp[i-1][k]+dp[i-1][k-1]
 
        # 1≤i≤N,1≤k≤8,Sのi文字目≠chokudaiのk文字目の場合
        else:
            # dp[i-1][k-1]:Sの(i-1)文字目までを使ってchokudaiの(k-1)文字目を作る場合(Sのi文字目を使う)
            dp[i][k]=dp[i-1][k]
                   
    # 余りを取る
    dp[i][k]%=mod

# SのN文字目までを使ってchokudaiの8文字目までを作る方法の数
print(dp[N][8])

28 全探索2 ABC233 C Dif:604

提出
# 入力の受け取り
N,X=list(map(int,input().split()))

# L,aの格納リスト
L=[]
a=[]

# N回
for i in range(N):
    # 一旦リストで受け取り
    tmp=list(map(int,input().split()))
    # リストの0番目=L
    L.append(tmp[0])
    # リストの1番目~=a
    a.append(tmp[1:])

# 全ての掛け算パターンの結果
Pro=[1]

# i=0~(N-1)
for i in range(N):
    # 一時的に結果を格納するリスト
    tmpPro=[]

    # i番目の袋のa全てについて
    for ai in a[i]:
        # ここまでの全ての掛け算パターンの結果
        for p in Pro:
            # 掛け算して格納
            tmpPro.append(ai*p)

    # ProをtmpProで更新
    Pro=tmpPro

# 結果がXとなったパターンを数える
ans=Pro.count(X)

# 答えを出力
print(ans)

29 BFS1 ABC204 C Dif:629

提出
# 入力の受け取り
N,M=map(int, input().split())

# 道路の情報を格納するリスト
connect=[[] for i in range(N+1)]

# M回受け取り
for i in range(M):
    # 入力の受け取り
    A,B=map(int, input().split())
    # connect[A]にBを追加
    # 都市1から都市2,3,4にいけるならconnect[1]=2,3,4
    connect[A].append(B)

# dequeをインポート
from collections import deque

# BFS
# 引数:スタート都市→返り値:スタート都市から行ける都市の数
def BFS(start):
    # 行ける都市を数える変数
    # スタート都市→スタート都市には必ず行けるから1
    count=1

    # 訪問済み都市のリスト
    # 訪問済みならTrue、未訪問ならFalse
    visited=[False]*(N+1)

    # スタート都市は訪問済みにする
    visited[start]=True

    # キューを用意
    que=deque()
    # キューへスタート都市を追加
    que.append(start)
  
    # キューが空になるまで
    while 0<len(que):
        # 今いる都市
        now=que.popleft()

        # 今いる都市から行ける都市を順にtoへ
        for to in connect[now]:
            # もしtoが未訪問なら
            if visited[to]==False:
                # countにプラス1
                count+=1

                # toを訪問済みにする
                visited[to]=True

                # キューへtoを追加
                que.append(to)

    # 行ける都市の数を返す
    return count

# 答えを格納する変数
ans=0

# x=1~N
for x in range(1,N+1):
    # xをスタート地点としたときに行ける都市の数を順に足し算
    ans+=BFS(x)

# 答えの出力
print(ans)

30 規則性利用 ABC238 C Dif:637

提出
# 余りを定義
mod=998244353

# 入力の受け取り
N=int(input())

# A~Bまでの和
# 引数:A,B→返り値:A~Bまでの和
def S(A,B):
    return (B-A+1)*(A+B)//2

# 答え
ans=0

# x~1~18
for x in range(1,19):
    # 10^x≤Nならば
    if 10**x<=N:
        # 「1~9*10**(x-1)までの和」
        ans+=S(1,9*10**(x-1))
        # 余りを取る
        ans%=mod
    # 10^(x-1)≤N<10^xならば
    else:
        # 「1~(N-10^(x-1)+1)までの和」
        ans+=S(1,N-10**(x-1)+1)
        # 余りを取る
        ans%=mod
        # forを抜ける
        break

# 答えの出力
print(ans)

31 全探索3 ABC227 C Dif:692

提出
# pypyで提出

# 入力の受け取り
N=int(input())

# 答えのカウント
ans=0

# 初期値
A=1
# A≤(Nの三乗根)⇔A^3≤Nの間
while A**3<=N:
    # 初期値
    B=A
    # B≤√(N/A)⇔A*B^2≤Nの間
    while A*B**2<=N:
        # ありうるCの個数=(N/AB)の切り捨て-B+1
        ans+=int(N/(A*B))-B+1
        # 次のBへ
        B+=1
    # 次のAへ
    A+=1

# 答えの出力
print(ans)

32 DFS1 ABC213 D Dif:710

提出
# 再帰回数上限。再帰関数を書くときは必ず最初に書くこと
import sys
sys.setrecursionlimit(10**6)

# 入力受け取り
N=int(input())

# 辺の情報格納
connect=[[] for i in range(N+1)]

# 辺の情報受け取り
for i in range(N-1):
    A,B=map(int, input().split())
    connect[A].append(B)
    connect[B].append(A)
# connect[1]=[2,3,4]ならば1と2,3,4がつながっている、というように確認できる

# 小さい順に回るからソート
for i in range(N+1):
    connect[i].sort()

# 答えの格納リスト
ans=[]

# DFS(今いる都市,前にいた都市)
def DFS(now,pre):
    # 今いる都市を答えに入れる
    ans.append(now)
    # to=今いる都市から行ける都市
    for to in connect[now]:
        # もしtoが前にいた都市と違うなら
        if to!=pre:
            # 更に先へ探索する
            DFS(to,now)
            # 戻ってきたら答えへ格納
            ans.append(now)

# 最初の都市=1,前にいた都市=-1(前にいた都市がないので存在しない番号)としてスタート
DFS(1,-1)

# 答えの出力
print(*ans)

33 連想配列2 ABC218 D Dif:715

提出
# 入力を受け取り
N=int(input())

# 座標の格納用リスト
points=[]

# defaultdictを用意 初期値は0
from collections import defaultdict
# (x,y)が存在したらp[(x,y)]=1
p=defaultdict(int)

# M行受け取り
for i in range(N):
    # x,yを受け取り
    x,y=map(int, input().split())
    # 座標をpointsへ格納
    points.append([x,y])
    # p[(x,y)]=1を記録
    p[(x,y)]=1

# 答えを格納する変数
ans=0

# p1=0~(N-1)
for p1 in range(N):
    # p2=(p1+1)~(N-1)
    for p2 in range(p1+1,N):
        # p1のx座標,y座標
        p1_x,p1_y=points[p1]
        # p1のx座標,y座標
        p2_x,p2_y=points[p2]
 
        # x座標またはy座標が同じ場合は
        if p1_x==p2_x or p1_y==p2_y:
            # 次の点へ
            continue
        # 座標(p1_x,p2_y)と座標(p2_x,p1_y)の点が存在すれば
        if p[(p1_x,p2_y)]==1 and p[(p2_x,p1_y)]==1:
            # 答えにプラス1
            ans+=1

# 二重に数えているので2で割る
ans//=2
# 答えを出力
print(ans)

34 UnionFind1 ATC B

提出
class UnionFind:
    def __init__(self,n):
        self.n=n
        self.parent_size=[-1]*n
    def leader(self,a):
        if self.parent_size[a]<0: return a
        self.parent_size[a]=self.leader(self.parent_size[a])
        return self.parent_size[a]
    def merge(self,a,b):
        x,y=self.leader(a),self.leader(b)
        if x == y: return
        if abs(self.parent_size[x])<abs(self.parent_size[y]):x,y=y,x
        self.parent_size[x] += self.parent_size[y]
        self.parent_size[y]=x
    def same(self,a,b):
        return self.leader(a) == self.leader(b)
    def size(self,a):
        return abs(self.parent_size[self.leader(a)])
    def groups(self):
        result=[[] for _ in range(self.n)]
        for i in range(self.n):
            result[self.leader(i)].append(i)
        return [r for r in result if r != []]
 
# 入力の受け取り
N,Q=map(int,input().split())
 
# UnionFindを用意
UF=UnionFind(N+1)
 
# Q回
for i in range(Q):
    # 入力の受け取り
    P,A,B=map(int,input().split())
 
    # P=0の場合
    if P==0:
        # A,Bを連結
        UF.merge(A,B)
   
    # P=1の場合
    else:
        # A,Bが連結なら
        if UF.same(A,B):
            # 「Yes」を出力
            print("Yes")
        # 連結でないなら
        else:
            # 「No」を出力
            print("No")

35 UnionFind2 ABC231 D Dif:726

提出
class UnionFind:
    def __init__(self,n):
        self.n=n
        self.parent_size=[-1]*n
    def leader(self,a):
        if self.parent_size[a]<0: return a
        self.parent_size[a]=self.leader(self.parent_size[a])
        return self.parent_size[a]
    def merge(self,a,b):
        x,y=self.leader(a),self.leader(b)
        if x == y: return
        if abs(self.parent_size[x])<abs(self.parent_size[y]):x,y=y,x
        self.parent_size[x] += self.parent_size[y]
        self.parent_size[y]=x
    def same(self,a,b):
        return self.leader(a) == self.leader(b)
    def size(self,a):
        return abs(self.parent_size[self.leader(a)])
    def groups(self):
        result=[[] for _ in range(self.n)]
        for i in range(self.n):
            result[self.leader(i)].append(i)
        return [r for r in result if r != []]

# 入力の受け取り
N,M=map(int,input().split())

# UnionFind 初期化
UF=UnionFind(N+1)

# 辺の本数をカウント
count=[0]*(N+1)

# M回
for i in range(M):
    # 入力の受け取り
    A,B=map(int,input().split())

    # 辺の本数をカウント
    count[A]+=1
    count[B]+=1
   
    # 辺の本数が3本以上なら
    if 3<=count[A] or 3<=count[B]:
        # 「No」を出力
        print("No")
        # 終了
        exit()

    # A,Bが連結の場合
    if UF.same(A,B)==True:
        # 「No」を出力
        print("No")
        # 終了
        exit()

    # そうでなければ(連結出ない場合)
    else:
        # A,Bに辺を張る(連結する)
        UF.merge(A,B)

# 「Yes」を出力
print("Yes")
別解
# 再帰回数上限。再帰関数を使うときは必ず最初に書くこと
import sys
sys.setrecursionlimit(10**6)

# 入力の受け取り
N,M=map(int,input().split())

# つながっている頂点の記録
Connect=[[] for i in range(N+1)]

# M回
for i in range(M):
    # 入力の受け取り
    A,B=map(int,input().split())

    # A→B、B→Aへ行ける
    Connect[A].append(B)
    Connect[B].append(A)
 
    # 辺の本数が3本以上なら
    if 3<=len(Connect[A]) or 3<=len(Connect[B]):
        # 「No」を出力
        print("No")
        # 終了
        exit()

# まだ訪問済みでない頂点
visited=[False]*(N+1)

# DFS(今いる頂点、直前にいた頂点)
def DFS(Now,Pre):
    # 今いる頂点を訪問済みにする
    visited[Now]=True

    # to=Nowから行ける頂点
    for to in Connect[Now]:
        # 直前にいた頂点でなければ
        if to!=Pre:
            # 訪問済みでなければ
            if visited[to]==False:
                # 次のDFSを開始
                DFS(to,Now)
            # 訪問済みであれば
            # ⇔ループになった
            else:
                # 「No」を出力
                print("No")
                # 終了
                exit()                

# i=1~N
for i in range(1,N+1):
    # 訪問済みでなければ
    if visited[i]==False:
        # DFSを開始
        # (直前にいた頂点はないので0にしておく)
        DFS(i,0)

# 「Yes」を出力
print("Yes")

36 尺取法1、区間和 ABC229 D Dif:745

提出
# 入力の受け取り
S=input()
K=int(input())

S="?"+S

# Sの長さ
N=len(S)

# 「.」の累積個数
Count=[0]*N

# i=1~(N-1)
for i in range(1,N):
    # S[i]=「X」ならば
    if S[i]=="X":
        # 一つ左と同じ
        Count[i]=Count[i-1]
    # そうでないなら(S[i]=「.」)
    else:
        # 一つ左+1
        Count[i]=Count[i-1]+1

# 答え
ans=0

# 右
r=1

# l=1~(N-1)
for l in range(1,N):
    # r<Nの間
    while r<N:
        # [左,右]にある「.」の数=Count[r]-Count[l-1]
        Period=Count[r]-Count[l-1]

        # [左,右]にある「.」の数≤Kならば
        # ⇔[左,右]にある「.」を全て「X」に変えられるなら
        if Period<=K:
            # 右を移動
            r+=1
        # そうでないなら([左,右]にある「.」を全て「X」に変えられないなら)
        else:
            # whileを抜ける
            break

    # [左,右-1]の長さを計算し、今までの答えより大きければ更新
    ans=max(ans,r-l)

# 答えの出力
print(ans)

37 BFS2 ABC211 D Dif:755

提出
# 入力の受け取り
N,M=map(int, input().split())

# 道路の情報を格納する変数
connect=[[] for i in range(N+1)]
# 道路の情報を受け取って格納
for i in range(M):
    A,B=map(int, input().split())
    connect[A].append(B)
    connect[B].append(A)

# 余りの定義
mod=10**9+7

# まだ到達していない都市の移動時間(infinity:無限大)
# 大きめの数にする
inf=10**15

# (1)各都市の最短移動時間を記録するリストtimeを作る(初期値は大きな数)
time=[inf]*(N+1)
# 都市①の最短移動時間は「0」
time[1]=0

# (2)各都市にたどり着くまでの経路数を記録するリストcountを作る
count=[0]*(N+1)
# 都市①に行く経路数は「1」
count[1]=1

# (3)キューを用意
from collections import deque
que=deque()
# キューに都市①を入れる
que.append(1)

# (6)(4)~(5)をキューが空になるまで繰り返す
while 0<len(que):
    # (4)キューの左端から要素(都市の番号)を取り出す(今いる街)
    now=que.popleft()

    # (5)今いる都市から行ける都市を確認する
    # nowから行ける都市を順にtoへ格納
    for to in connect[now]:
        # もし行ける都市の移動時間がinfならば(まだ更新されていない)
        if time[to]==inf:
            # (5-1)「経路数」=「今いる都市の経路数」
            count[to]=count[now]
            # (5-2)「最短移動時間」=「今いる都市の最短移動時間+1」
            time[to]=time[now]+1
            # (5-3)キューに追加
            que.append(to)

        # そうでないなら(移動時間が更新済み)
        else:
            # 「最短移動時間」=「今いる都市の最短移動時間+1」(最短経路)ならば
            if time[to]==time[now]+1:
                # (5-4)「経路数」+=「今いる都市の経路数」
                count[to]+=count[now]

        # 余りを取る
        count[to]%=mod

# (7)答えを出力する
# Nが未到達であれば(「最短移動時間」が更新されていなければ)
if time[N]==inf:
    # たどり着けないため「0」を出力
    print(0)
  
# そうでないならば
else:
    # count[N]を出力
    print(count[N])

38 シミュレーション2 ABC243 D Dif:758

提出
# 入力の受け取り
N,X=map(int,input().split())
S=input()

# 移動の記録
Move=[]

# i=0~(N-1)
for i in range(N):
    # ・記録が空の場合
    if len(Move)==0:
        # S[i]を記録
        Move.append(S[i])
   
    # ・記録が空でない場合
    else:
        # ・S[i]が「L」または「R」
        if S[i]=="L" or S[i]=="R":
            # S[i]を記録
            Move.append(S[i])
        # ・S[i]が「U」
        else:
            # ・S[i]が「U」かつ記録の末尾が「L」または「R」(「LU」「RU」になる場合)
            if Move[-1]=="L" or Move[-1]=="R":
                # 記録の末尾を消す
                Move.pop()
            # ・S[i]が「U」かつ記録の末尾が「U」
            else:
                # 「U」を記録
                Move.append("U")

# シミュレーション
for s in Move:
    # 「L」ならば2Xへ移動
    if s=="L":
        X*=2
    # 「R」ならば(2X+1)へ移動
    elif s=="R":
        X=2*X+1
    # 「U」ならばX//2へ移動
    else:
        X//=2

# 答えの出力
print(X)

39 DP2 ABC248 C Dif:787

提出
# pypyで提出

# 入力の受け取り
N,M,K=map(int,input().split())

# 余りの定義
mod=998244353

# (1)表を作る
dp=[[0]*(K+1) for i in range(N+1)]

# (2)すぐにわかるところを埋める
# ・(x≤M)dp[1][x]=1
# ・(M<x)dp[1][x]=0
for x in range(1,M+1):
    dp[1][x]=1

# (3)表の小さい方から答えにたどり着くまで埋める
# i=2~N
for i in range(2,N+1):
    # x=1~K
    for x in range(1,K+1):
        # j=1~(x-1)
        for j in range(1,x):
            # ・(2≤i,1≤j≤x-1)x-j≤Mならばdp[i][x]+=dp[i-1][j]
            if x-j<=M:
                dp[i][x]+=dp[i-1][j]
                # 余りを取る
                dp[i][x]%=mod

# (4)答えを出力する
# 答え
ans=0

# x=1~K
for x in range(1,K+1):
    # dp[N][1]~dp[N][K]の和
    ans+=dp[N][x]
    # 余りを取る
    ans%=mod

# 答えを出力
print(ans)

40 二分探索2 ABC248 D Dif:793

提出
# pypyで提出
 
# 入力の受け取り
N=int(input())
A=list(map(int,input().split()))
 
# 1,2,3,...が何番目にあるかの記録 左端には「0」を入れておく
Aindx=[[0] for i in range(10**6)]
 
# i=0~(N-1)
for i in range(N):
    # インデックス番号を記録
    # 1インデックスなので「i+1」を記録することに注意
    Aindx[A[i]].append(i+1)
 
# i=0~(N-1)
for i in range(10**6):
    # 右端に∞=10^6を追加
    Aindx[i].append(10**6)
 
# Xがあるインデックス番号のうちL以上で最小のもの
def NibutanLeft(X,L):
    # (1)左=区間の最小、右=区間の最大とする
    # 左
    l=0
    # 右(=長さ-1)
    r=len(Aindx[X])-1
 
    # (4)1<(右-左)となっている間(2)~(4)を繰り返す
    while 1<r-l:
        # (2)中央=(左+右)//2が条件を満たすか確認
        # 中央=(左+右)//2
        c=(l+r)//2
 
        # (3)(2)の結果より左または右を更新する
        # ・(中央)番目の数がL以上
        if L<=Aindx[X][c]:
            # 左=中央と更新
            r=c
        # ・(中央)番目の数がLより小さい
        else:
            # 右=中央と更新
            l=c
 
    # 右を返す
    return r
 
# Xがあるインデックス番号のうちR以下で最大のもの
def NibutanRight(X,R):
    # (1)左=区間の最小、右=区間の最大とする
    # 左
    l=0
    # 右(=長さ-1)
    r=len(Aindx[X])-1
 
    # (4)1<(右-左)となっている間(2)~(4)を繰り返す
    while 1<r-l:
        # (2)中央=(左+右)//2が条件を満たすか確認
        # 中央=(左+右)//2
        c=(l+r)//2
 
        # (3)(2)の結果より左または右を更新する
        # ・(中央)番目の数がR以下
        if Aindx[X][c]<=R:
            # 左=中央と更新
            l=c
        # ・(中央)番目の数がRより大きい
        else:
            # 右=中央と更新
            r=c
 
    # 右を返す
    return l
 
# 入力の受け取り
Q=int(input())

# Q回
for i in range(Q):
    # 入力の受け取り
    L,R,X=map(int,input().split())
 
    # 「Xがあるインデックス番号のうちL以上で最小のもの」
    Lindx=NibutanLeft(X, L)
    # 「Xがあるインデックス番号のうちR以下で最大のもの」
    Rindx=NibutanRight(X, R)
    # 答えを出力
    print(Rindx-Lindx+1)
別解
# 入力の受け取り
N=int(input())
A=list(map(int,input().split()))

# 1,2,3,...が何番目にあるかの記録 左端には「0」を入れておく
Aindx=[[0] for i in range(10**6)]

# i=0~(N-1)
for i in range(N):
    # インデックス番号を記録
    # 1インデックスなので「i+1」を記録することに注意
    Aindx[A[i]].append(i+1)

# i=0~(N-1)
for i in range(10**6):
    # 右端に∞=10^6を追加
    Aindx[i].append(10**6)

# 入力の受け取り
Q=int(input())

# bisectをインポート
import bisect

# Q回
for i in range(Q):
    # 入力の受け取り
    L,R,X=map(int,input().split())

    # Lを大小関係を保ったままリストに挿入する位置のインデックス(同じ数があれば左側へ)
    Lindx=bisect.bisect_left(Aindx[X], L)
    # Rを大小関係を保ったままリストに挿入する位置のインデックス(同じ数があれば右側へ)
    Rindx=bisect.bisect_right(Aindx[X], R)
    # 答えを出力
    print(Rindx-Lindx)

41 尺取法2、エラトステネスの篩 ABC250 D Dif:797

提出
# エラトステネスの篩
def Eratosthenes(N):
    # 素数であるかの判定リスト
    IsPrime=[True]*(N+1)

    # i=2,3,4,...
    i=2
    # i≤√Nまで⇔i^2≤Nまで
    while i**2<=N:
        # iが素数でなければ
        if IsPrime[i]==False:
            # 次のiへ
            i+=1
            continue
       
        # k=2,3,4,...
        k=2
        while i*k<=N:
            # iの倍数は素数でない
            IsPrime[i*k]=False
            # 次のkへ
            k+=1

        # 次のkへ
        i+=1

    # 素数リスト
    PList=[]

    # i=2~N
    for i in range(2,N+1):
        # iが素数ならば
        if IsPrime[i]==True:
            # リストへ入れる
            PList.append(i)

    # リストを返す
    return PList

# 入力の受け取り
N=int(input())
# 10^6以下の素数リストを作成
P=Eratosthenes(10**6)

# 答え
ans=0

# 素数リストの長さ
lenP=len(P)

# 最後の素数の番号(0インデックス)
k=lenP-1

# i=0~(lenP-1)
for i in range(lenP):
 
    # p=i番目の素数(0インデックス)
    # q=k番目の素数(0インデックス)
    # p*q^3≤Nとなるまでkを減らしていく
    while i<k and N<P[i]*P[k]**3:
        k-=1

    # k≤iとなったら
    if k<=i:
        # 答えの出力
        print(ans)
        # 途中終了
        exit()

    # i+1,i+2,...,k番目の素数までqとして使用できる
    # ⇔(k-i)個
    ans+=k-i
別解
def Eratosthenes(N):
    IsPrime=[True]*(N+1)
 
    i=2
    while i**2<=N:
        if IsPrime[i]==False:
            i+=1
            continue
       
        k=2
        while i*k<=N:
            IsPrime[i*k]=False
            k+=1
 
        i+=1
 
    PList=[]
 
    for i in range(2,N+1):
        if IsPrime[i]==True:
            PList.append(i)
 
    return PList

# 入力の受け取り
N=int(input())
# 素数リストを作る
P=Eratosthenes(10**6)

# 素数リストの長さ
lenP=len(P)

# 二分探索
def Nibutan(i):
    # 左
    l=0
    # 右
    r=lenP-1

    # 1<(右-左)ならば
    while 1<(r-l):
        # 中央=(左+右)//2
        c=(l+r)//2

        # P[i]=i番目の素数
        # P[c]=c番目の素数
        # 条件を満たすなら
        if P[i]*P[c]**3<=N:
            # 左=中央と更新
            l=c
        # 条件を満たさないなら
        else:
            # 右=中央と更新
            r=c

    # 左を返す
    return l

# 答え
ans=0

# i=0~(素数リストの長さ-1)
for i in range(lenP):
    # P[i]*P[k]^3≤Nとなるもののうち最大のk
    k=Nibutan(i)
    # i<kならば
    if i<k:
        # (k-i)個プラス
        ans+=k-i
    # そうでないなら
    else:
        # 探索終了
        break

# 答えを出力
print(ans)

42 FenwickTree ACL B

提出
class FenwickTree:
    def __init__(self,N):
        self.N=N
        self.F=[0]*N
 
    def add(self,i,x):
        i+=1
        while i<=self.N:
            self.F[i-1]+=x
            i+=i&-i
 
    def sum_r(self,r):
        s=0
        while 0<r:
            s+=self.F[r-1]
            r-=r&-r
        return s
 
    def sum(self,l,r):
        return self.sum_r(r+1)-self.sum_r(l)
 
    def select(self,i):
        return self.sum(i,i)
 
# 入力の受け取り
N,Q=map(int,input().split())
a=list(map(int,input().split()))
 
# 長さ(N+1)のFenwickTreeを用意
# 初期値は全て0
FT=FenwickTree(N+1)
 
# i=0~(N-1)
for i in range(N):
    # i番目にa[i]を足す
    FT.add(i, a[i])
 
# Q回
for i in range(Q):
    # 入力の受け取り
    q,a,b=map(int,input().split())
 
    # q=0の場合
    if q==0:
        # a番目にbを足す(p番目にxを足す)
        FT.add(a, b)
    # q=1の場合
    else:
        # a~(b-1)番目の区間和を出力(l~(r-1)番目の区間和を出力)
        print(FT.sum(a, b-1))

43 想定解multiset ABC217 D Dif:802

提出
# 提出はpypyで行う

# Fenwick_Tree
class Fenwick_Tree:
    def __init__(self,n):
        self._n=n
        self.data=[0]*n
    def add(self,p,x):
        p+=1
        while p<=self._n:
            self.data[p-1] +=x
            p+=p&-p
    def _sum(self,r):
        s=0
        while 0<r:
            s+=self.data[r-1]
            r-=r&-r
        return s
    def sum(self,l,r):
        r+=1
        return self._sum(r)-self._sum(l)
    def select(self,p):
        return self.sum(p,p)

# 入力の受け取り
L,Q=map(int, input().split())

# クエリの記録用リスト
query=[]

# カットする場所を予め記録するリスト
cut=[]

# Q回
for i in range(Q):
    # 入力の受け取り
    c,x=map(int, input().split())
    # クエリを記録
    query.append([c,x])
    # c=1ならば
    if c==1:
        # cutに場所を記録
        cut.append(x)

# cutに「0」を追加
cut.append(0)
# cutに「L」を追加
cut.append(L)

# cutをソート
cut.sort()

# cutの長さをNとする
N=len(cut)

# x(カットする場所)→インデックス番号への変換
cut_index=dict()

# 変換表の作成
for i in range(N):
    cut_index[cut[i]]=i

# FenwickTreeの作成
Fenwick=Fenwick_Tree(N)

# 左端(0)に「1」を立てる(1を足す)
Fenwick.add(0,1)
# 右端(Lのインデックス番号)に「1」を立てる(1を足す)
Fenwick.add(N-1,1)

# xがどのインデックス番号の間にあるか確認する二分探索
# 引数:x→返り値:cut[l]<x<cut[r]を満たす最大のl、最小のr
def Nibutan_x(x):
    # 左(left)=0
    l=0
    # 右(right)=N-1
    r=N-1

    # 1<(右-左)の間
    while 1<r-l:
        # 中央(center)=(l+r)//2
        c=(l+r)//2
        # cut[c]<xなら
        if cut[c]<x:
            # 左=c
            l=c
        # x<cut[c]なら
        else:
            # 右端=c
            r=c

    # 左、右を返す
    return l,r

# xより左で1が立っている場所のうち、一番近いものを二分探索
# 引数:x→返り値:Fenwickの区間和[k~x]が1以上となるもののうち、最大のk
def Nibutan_l(x):
    # 左(left)=0
    l=0
    # 右(right)=x
    r=x

    # 1<(右-左)の間
    while 1<r-l:
        # 中央(center)=(l+r)//2
        c=(l+r)//2
        # 区間和[c~x]が1以上
        # ⇔区間c~xに「1」が1つ以上立っている
        if 1<=Fenwick.sum(c,x):
            # 左=中央
            l=c
        # 区間和[c~x]が1未満(=0)
        # ⇔区間c~xに「1」が立っていない
        else:
            # 右=中央
            r=c

    # 区間和[r~x]が1ならば
    if Fenwick.sum(r,x)==1:
        # rを返す
        return r
    # そうでなければ
    else:
        # lを返す
        return l

# xより右で1が立っている場所のうち、一番近いものを二分探索
# 引数:x→返り値:Fenwickの区間和[x~k]が1以上となるもののうち、最小のk
def Nibutan_r(x):
    # 左(left)=x
    l=x
    # 右(right)=N-1
    r=N-1

    # 1<(右-左)の間
    while 1<r-l:
        # 中央(center)=(l+r)//2
        c=(l+r)//2
        # 区間和[x~c]が1以上
        # ⇔区間x~cに「1」が1つ以上立っている
        if 1<=Fenwick.sum(x,c):
            # 右=中央
            r=c
        # 区間和[x~c]が1未満(=0)
        # ⇔区間x~cに「1」が立っていない
        else:
            # 左=中央
            l=c

    # 区間和[x~l]が1ならば
    if Fenwick.sum(x,l)==1:
        # lを返す
        return l
    # そうでなければ
    else:
        # rを返す
        return r

# クエリを読み込み
for c,x in query:
    # c=1の場合
    if c==1:
        # cut_index[i]の部分に「1」を立てる(+1する)
        Fenwick.add(cut_index[x],1)
    # c=2の場合
    else:
        # xがどのインデックス番号の間にあるか確認する二分探索
        l_x,r_x=Nibutan_x(x)
        # xより左で「1」が立っている場所のうち、一番近い場所のインデックス番号を二分探索
        l_index=Nibutan_l(l_x)
        # xより右で「1」が立っている場所のうち、一番近い場所のインデックス番号を二分探索
        r_index=Nibutan_r(r_x)
        # 右の値-左の値
        print(cut[r_index]-cut[l_index])
別解
import bisect
from array import array

# 入力の受け取り
L,Q=map(int,input().split())

# カット位置を記録するarray
# array(型コード,値)
cut=array("i",[0,L])

# Q回
for i in range(Q):
    # 入力の受け取り
    c,x=map(int,input().split())
    # c=1の場合
    if c==1:
        # xをx以上で最小の要素の次に挿入
        bisect.insort(cut,x)
    # それ以外(c=2の場合)
    else:
        # x以上で最小の要素のインデックス番号を取得
        index=bisect.bisect(cut,x)
        # 長さを出力
        print(cut[index]-cut[index-1])

44 DP3 ABC204 D Dif:832

提出
# pypyで提出

# 入力の受け取り
N=int(input())
# Tは先頭に[0]を追加して受け取り
T=[0]+list(map(int, input().split()))

# Tの合計
T_sum=sum(T)

# (1)表を作る
# 『i番目までの数を組み合わせてKを作れるか』
# 例:『3番目までの数を組み合わせて「7」を作れる』→ dp[3][7]=True
dp=[[False]*(T_sum+1) for i in range(N+1)]

# (2)すぐにわかるところを埋める
# 『0番目までの数を組み合わせて「0」を作れる
dp[0][0]=True

# (3)表の小さい方から答えにたどり着くまで埋める
# i=1~N
for i in range(1,N+1):
    # K=0~T_sum Kを作れるか確認
    for K in range(T_sum+1):
        # 『(i-1)番目までの数を組み合わせてKを作れる』(→dp[i-1][K]=True)ならば
        if dp[i-1][K]==True:
            # 『i番目までの数を組み合わせてKを作れる』(→dp[i][K]=True)
            dp[i][K]=True
        # 0<=K-T[i] かつ『(i-1)番目までの数を組み合わせてK-T[i]を作れる』ならば(dp[i-1][K-T[i]]=True)
        if 0<=K-T[i] and dp[i-1][K-T[i]]==True:
            # 『i番目までの数を組み合わせてKを作れる』(→dp[i][K]=True)            
            dp[i][K]=True

# 答えを格納する変数(初期値はバカでかい数)
ans=10**15

# (4)答えを出力する
# K=0~T_sum
for K in range(T_sum+1):
    # 『N番目までの数を組み合わせてKを作れる』ならば
    if dp[N][K]==True:
        # max(K,T_sum-K)が料理をすべて作るのにかかる時間=答えの候補
        # それまでのansより小さければ更新
        ans=min(ans,max(K,T_sum-K))

# 答えの出力
print(ans)

45 区間スケジューリング ABC230 D Dif:963

提出
# 入力の受け取り
N,D=map(int,input().split())

# 区間の情報
Section=[]

# N回
for i in range(N):
    # 入力の受け取り
    L,R=map(int,input().split())
    # 情報を格納
    Section.append([L,R])

# 右端の列番号を基準にソート
Section.sort(key=lambda x:x[1])

# 最初の壁の右端にパンチを打つ
X=Section[0][1]

# 答え
ans=1

# i=1~(N-1)
for i in range(1,N):
    # i番目の壁の左端、右端
    Li,Ri=Section[i][0],Section[i][1]
    # 最後のパンチでi番目の壁を壊せていなければ
    # ⇔最後にパンチした位置+(D-1)<左端
    if X+D-1<Li:
        # 右端にパンチを打つ
        X=Ri
        # 回数をカウント
        ans+=1

# 答えの出力
print(ans)

46 UnionFind3 ABC218 E Dif:1004

提出
# UnionFind
class UnionFind:
    def __init__(self,n):
        self.n=n
        self.parent_size=[-1]*n
    def leader(self,a):
        if self.parent_size[a]<0: return a
        self.parent_size[a]=self.leader(self.parent_size[a])
        return self.parent_size[a]
    def merge(self,a,b):
        x,y=self.leader(a),self.leader(b)
        if x == y: return
        if abs(self.parent_size[x])<abs(self.parent_size[y]):x,y=y,x
        self.parent_size[x] += self.parent_size[y]
        self.parent_size[y]=x
    def same(self,a,b):
        return self.leader(a) == self.leader(b)
    def size(self,a):
        return abs(self.parent_size[self.leader(a)])  
    def groups(self):
        result=[[] for _ in range(self.n)]
        for i in range(self.n):
            result[self.leader(i)].append(i)
        return [r for r in result if r != []]

# 入力の受け取り
N,M=map(int, input().split())

# 辺の情報格納用リスト
edge=[]

# M行受け取り
for i in range(M):
    A,B,C=map(int, input().split())
    # 後のソートのためC先頭で格納
    edge.append([C,A,B])

# (1)辺をCの小さい順に並び替える
edge.sort()

# 報酬
ans=0

# (2)すべての辺を取り除き、報酬と罰金の合計を計算する
for i in range(M):
    ans+=edge[i][0]

# UnionFindを初期化(頂点数(N+1)個(0~N))
UF=UnionFind(N+1)

# edgeの各要素について
for C,A,B in edge:
    # (3)Cが小さい方から辺を確認していく
    # ・Cが0以下なら
    if C<=0:
        # 頂点Ai,Biを連結し、罰金|C|を報酬にプラスする(Cがマイナスの辺は取り除く理由がない)
        # 連結
        UF.merge(A,B)
        # 罰金=|C|をプラス
        ans+=abs(C)

    # そうでないならば(cが0より大きいなら)
    else:
        # ・頂点Ai,Biが非連結なら
        if UF.same(A,B)==False:
            # 頂点Ai,Biを連結し、報酬からCを引く
            # 報酬からCを引く
            ans-=C
            # A,Bを連結
            UF.merge(A,B)

# 答えを出力
print(ans)

47 DFS2 ABC239 E Dif:1084

提出
# 入力の受け取り
N,Q=map(int,input().split())
# 1インデックスにするため先頭に「0」を追加
X=[0]+list(map(int,input().split()))
# 辺の情報格納用
edge=[[] for i in range(N+1)]

# (N-1)回
for i in range(N-1):
    # 入力の受け取り
    A,B=map(int,input().split())
    # 辺の情報を格納
    edge[A].append(B)
    edge[B].append(A)

# 部分木の頂点に書いている数を大きい順に格納したリスト
# 1インデックスにするため0番目は埋めておく
P=[[0]]

# (1)「部分木に含まれる数を大きい順にソートした二次元配列」をPとし、自分自身に書いている数をPへ記録する
for i in range(1,N+1):
    # Pへ自分自身に書いている数を追加
    P.append([X[i]])

# (2)キューを用意する
que=list()

# (3)スタート地点=頂点①をキューへ入れる
# (今いる頂点,今いる頂点の親,訪問回数)
que.append((1,0,1))

# (4)キューが空になるまで(3)を繰り返す
while 0<len(que):
    # (4)キューの「右端から」要素を取り出す
    # (今いる頂点,今いる頂点の親,訪問回数)
    now,parent,count=que.pop()

    # ・1回目の訪問ならば
    if count==1:
        # (4-1)「今いる頂点」を2回目の訪問としてキューへ記録
        que.append((now,parent,2))
        # (4-2)「今いる頂点から行ける(親でない)頂点」をキューへ1回目の訪問として記録
        # to:今いる頂点から行ける頂点
        for to in edge[now]:
            # 親でなければ
            if to!=parent:
                # キューへ記録
                que.append((to,now,1))

    # ・2回目の訪問ならば
    else:
        # to:今いる頂点から行ける頂点
        for to in edge[now]:
            # (4-3)「今いる頂点」のPへ子の頂点のPを追加
            # 親ならば
            if to==parent:
                # 次の頂点へ
                continue
            P[now]+=P[to]
            # (4-4)大きい順にソート
            P[now].sort(reverse=True)
            # (4-5)20番目以降の要素を捨てる
            P[now]=P[now][:20]

# Q回
for i in range(Q):
    # 入力の受け取り
    V,K=map(int,input().split())
    # Kをマイナス1(P[v]は先頭が0番目、次が1番目、...のため)
    K-=1
    # 答えを出力
    print(P[V][K])

48 DP4 ABC219 D Dif:1085

提出
# pypyで提出

# 入力の受け取り
N=int(input())
X,Y=map(int, input().split())

# バカでかい数を作っておく(infinity)
inf=10**15

# (1)表を作る
# dp[i][x][y]:「i種類目までの弁当を使い、x個のたこ焼きとy個のたい焼きを手に入れるために必要な弁当の最小個数」
# 初期値はinf
dp=[[[inf]*(Y+1) for i in range(X+1)] for j in range(N+1)]

# (2)すぐにわかるところを埋める
# 「0種類目までの弁当を使い、0個のたこ焼きと0個のたい焼きを手に入れる最小個数」=0
dp[0][0][0]=0

# (3)表の小さい方から答えにたどり着くまで埋める
# i=1~N
for i in range(1,N+1):
    # 入力の受け取り
    A,B=map(int, input().split())
    # たこ焼きの数:x=0~X
    for x in range(X+1):
        # たい焼きの数:y=0~Y
        for y in range(Y+1):
            # 「買わない場合」(すでに埋まっている数のほうが小さい場合は更新しない)      
            dp[i][x][y]=min(dp[i][x][y],dp[i-1][x][y])
 
            # 「買う場合」(すでに埋まっている数のほうが小さい場合は更新しない)
            # たこ焼きの数がX以上→Xへ変換
            x_plus=min(x+A,X)
            # たい焼きの数がY以上→Yへ変換
            y_plus=min(y+B,Y)
            dp[i][x_plus][y_plus]=min(dp[i][x_plus][y_plus],dp[i-1][x][y]+1)

# 答え:「N種類目までの弁当を使い、X個のたこ焼きとY個のたい焼きを手に入れるために必要な弁当の最小個数」
ans=dp[N][X][Y]

# (4)答えを出力する
# もし答えがinfだったら(X個以上のたこ焼き、Y個以上のたい焼きを手に入れられない場合)
if ans==inf:
    # -1を出力
    print(-1)
# そうでないならば
else:
    # 答えを出力
    print(ans)

49 二分探索3 ABC246 D Dif:1148

提出
# pypyで提出

# 入力の受け取り
N=int(input())

# 関数にする
def f(a,b):
    return a**3+a**2*b+a*b**2+b**3

# 答え
ans=10**20

# b=0,1,2,...10^6
# (10^6より少し大きめにしている)
for b in range(10**6+100):

    # (1)左=区間の最小、右=区間の最大 とする
    # 左
    l=0
    # 右
    r=10**6+100

    # 1<(右-左)の間
    while 1<r-l:
        # (2)中央=(左+右)//2が条件を満たすか確認
        c=(r+l)//2

        # (3)(2)の結果より左または右を更新する
        # 計算結果がN未満なら
        if f(c,b)<N:
            # 左=中央と更新
            l=c
        # 計算結果がN以上なら
        else:
            # 右=中央と更新
            r=c

    # N≤f(l,b)ならば
    if N<=f(l,b):
        # f(l,b)がansより小さければ更新
        ans=min(ans,f(l,b))
    # そうでなければ(f(l,b)<N⇔f(r,b)≤N)
    else:
        # f(r,b)がansより小さければ更新
        ans=min(ans,f(r,b))    

# 答えの出力
print(ans)

50 ワーシャルフロイド法 ABC208 D Dif:1190

提出
# pypyで提出

# 入力の受け取り
N,M=map(int, input().split())

# 到達不可能時間(大きすぎるとTLEするので注意)
inf=10**15
# 時間表
time=[[inf]*(N+1) for i in range(N+1)]

# i=1~Nまで
for i in range(1,N+1):
    # 都市①→都市①,都市②→都市②、...を時間0へ
    time[i][i]=0

# M回
for i in range(M):
    # 入力の受け取り
    A,B,C=map(int, input().split())
    # 時間表の更新
    time[A][B]=C

# 答えを格納する変数
ans=0

# k=1~N
for k in range(1,N+1):
    # 新しい時間表
    new_time=[[0]*(N+1) for i in range(N+1)]

    # スタート都市:1~N
    for start in range(1,N+1):
        # ゴール都市:1~N
        for goal in range(1,N+1):
            # 新しい時間表を更新
            # 「(K-1)以下の都市を通って良いパターン」と「都市kを経由するパターン」の小さい方
            new_time[start][goal]=min(time[start][goal],time[start][k]+time[k][goal])

           
    # スタート都市:1~N
    for start in range(1,N+1):
        # ゴール都市:1~N
        for goal in range(1,N+1):
             # 新しい時間表でスタート→ゴールが到達不能でなければ
            if new_time[start][goal]!=inf:
                # 新しい時間を答えにプラス
                ans+=new_time[start][goal]
 
    # 古い時間表を新しい時間表へ更新
    time=new_time

# 答えの出力
print(ans)

クラス解説:UnionFind

# UnionFind
class UnionFind:
    # UnionFind(N):要素数Nで初期化。
    # 引数:N(要素数) → 返り値:なし
    def __init__(self,N):
        # 要素数
        self.N=N
        # 根の番号 と 木の要素数
        # マイナスの場合:グループの要素数(自身が根)
        # プラスの場合:根の番号
        self.parent_size=[-1]*N

    # leader(a):aの根を返す
    # 引数:a → 返り値:aの根
    def leader(self,a):
        # aが根ならa自身を返す
        if self.parent_size[a]<0: return a
        # aが根でないなら根に向かって木をたどる+根の更新
        self.parent_size[a]=self.leader(self.parent_size[a])
        # 根を返す
        return self.parent_size[a]

    # merge(a,b):aとbを連結
    # 引数:a,b → 返り値:なし
    def merge(self,a,b):
        # a,bの根をx,yへ
        x,y=self.leader(a),self.leader(b)
        # 根が同じなら終了
        if x == y: return
        # 木の要素数を比較 小さい方を大きい方につなげるため
        # x<yならばx,yを入れ替える(xを大きい方にしたい)
        if abs(self.parent_size[x])<abs(self.parent_size[y]):x,y=y,x
        # 要素数の更新:小さい方の要素数を大きい方の要素数に足す
        self.parent_size[x] += self.parent_size[y]
        # 要素数が小さい方の根を大きい方の根につなげる
        self.parent_size[y]=x

    # same(a,b):aとbの根が同じか確認
    # 引数:a,b → 返り値:True(根が同じ) False(根が違う)
    def same(self,a,b):
        # 根を比較し、同じならTrueを返す
        return self.leader(a) == self.leader(b)

    # size(a):aが属する木の要素数
    # 引数:a → 返り値:aが属する木の要素数
    def size(self,a):
        # 根の絶対値(=要素数)を返す
        return abs(self.parent_size[self.leader(a)])

    # groups():それぞれの木の内容を二次元配列として返す
    # 引数:なし → 返り値:木の内容
    def groups(self):
        # グループの格納リストを作る
        result=[[] for _ in range(self.N)]
        # リストの生成
        for i in range(self.N):
            result[self.leader(i)].append(i)
        # 空の要素を消す
        return [r for r in result if r!=[]]

クラス解説:FenwickTree

# FenwickTree
class FenwickTree:
    # 「FenwickTree(N):要素数Nで初期化」
    # 引数:N→返り値:なし
    def __init__(self,N):
        self.N=N
        # F:長さNのリスト
        self.F=[0]*N

    # 「add(i,x):i番目の要素にxを加算」
    # 引数:i,x→返り値:なし
    def add(self,i,x):
        # 1インデックスにするため1を加算
        i+=1
        # i≤Nの間
        while i<=self.N:
            # xを加算
            # iはプラス1されているのでF[i-1]に加算
            self.F[i-1]+=x
            # 次のi
            i+=i&-i

    # 「sum_r(r):区間[0,r)の区間和を計算」
    # 引数:r→返り値:区間[0,r)の区間和
    def sum_r(self,r):
        # 合計
        s=0
        # 0<rの間
        while 0<r:
            # sに加算
            s+=self.F[r-1]
            # 次のr
            r-=r&-r
        # 合計を返す
        return s

    # 「sum(l,r):区間[l,r]の区間和を計算」
    # 引数:l,r→返り値:区間[l,r]の区間和
    def sum(self,l,r):
        # 「区間[l,r]の区間和」=「区間[0,r+1)の区間和」-「区間[0,l)の区間和」
        return self.sum_r(r+1)-self.sum_r(l)

    # 「select(i):i番目の要素を出力」
    # 引数:i→返り値:i番目の要素
    def select(self,i):
        # 区間[i,i]の区間和
        return self.sum(i,i)
6
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
5