6
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

AtCoder Beginner Contest 147

Last updated at Posted at 2019-12-08

https://atcoder.jp/contests/abc147
解説
numpyを利用できるかよ!今度注意する。

AとBを書くまでもない。

###C - HonestOrUnkind2

bit全探索で解く。

3
1
2 1
1
1 1
1
2 0
を例としてやりましょう。
n = 3で、全員のH(Honest)(Unkind)状況は、$2^{3}=8$つ可能性がある。
例えば、101は、人1と人3が正直者、人2が不親切者である状況を示す。
ならば正直者の証言に矛盾があるかどうか、それをチェックすればいい。
人1の「人2が1です」証言は、101に矛盾するので、101が不可能であることがわかる。


n = int(input())
lst = []  # 証言list
for _ in range(n):
    a = int(input())
    lst.append([[int(i) for i in input().split()] for _ in range(a)])

m = 0
for i in range(2 ** n):
    a = True  # bin(i)が示す状況をTrueと仮定する。
    for j in range(n):
        if i >> j & 1:
'''
bin(i)のどの位が1か、現時点では私がこれをしか利用できない
101の場合、j=0,2の時条件を満たす(101>>0=1, 101>>1=10, 101>>2=1)
'''
            for x, y in lst[j]:  # 人jの証言をチェックする。ここでlst[0] = [2, 1]
                if (i >> (x - 1) & 1) != y:  # 101>>1&1=0, y=1, 矛盾
                    a = False  # iがだめだ
                    break
'''
011の場合、j=0,1:
j=0: [x,y]=[2,1], 011>>1&1=1, y=1, OK
j=1: [x,y]=[1,1], 011>>0&1=1, y=1, OK
aがTrueのまま
'''
    if a:
        m = max(m, sum(map(int, bin(i)[2:])))
# 011に1が幾つあるか、現時点では私がこれをしか利用できない

print(m)

###D - Xor Sum 4

10
3 1 4 1 5 9 2 6 5 3
を例として計算しよう。
3 = 0011
1 = 0001
4 = 0100
1 = 0001
5 = 0101
9 = 1001
2 = 0010
6 = 0110
5 = 0101
3 = 0011
各数字の各bitが、他の数字とN-1回XOR算しなければならない。
XOR算は、
1 xor 1 = 0 xor 0 = 0, 1 xor 0 = 0 xor 1 = 1
です。
1位を見ると、7つ'1'と3つ'0'があることがわかる。
つまり、全部45回のXOR算に、結果の1位が1になったのは21回。
2、3、4位には、別々24回、24回、9回ある。

つまり、最後の結果は、
21 * 1 + 24 * 2 + 24 * 4 + 9 * 8 = 237
です。

よって、


import numpy as np
 
n = int(input())
arr = np.array([int(i) for i in input().split()])
mod = 10 ** 9 + 7
s = 0

for i in range(60):
    c1 = np.count_nonzero(arr & 1) # 自分がnp.sumを利用したがどうしても正解になれなかった。なぜ?
    s += 2 ** i * c1 * (n - c1)
    arr >>= 1

print(s % mod)

###E - Balanced Path

自分ができないから他人のコードを拝見し参考した。
https://atcoder.jp/contests/abc147/submissions/8874312

先ずはarrayを作る。


import numpy as np
H, W = map(int, input().split())
lst1 = []
lst2 = []
for _ in range(H):
    lst1.append([int(i) for i in input().split()])
for _ in range(H):
    lst2.append([int(i) for i in input().split()])
arr1, arr2 = np.array(lst1), np.array(lst2)
arr = np.abs(arr1 - arr2)
'''
2 3
1 10 80
80 10 1
1 2 3
4 5 6
を例として、
arr = array([[0, 8, 77], [76, 5, 5]])
'''

つぎにbitを使う。
0<=A,B<=80ので、偏りは最大で80(H+W)まで考える必要がある。(by解説、実は80(H+W-1)まででも構わない)


d = [[0] * W for _ in range(H)]
m = 80 * (H + W)  # 400
d[0][0] = 1 << m  # 最初の「位置」
for h in range(H):
    for w in range(W):
        x = arr[h][w]  # 現在地の偏りを取る
        if h > 0:
            d[h][w] |= d[h - 1][w]  # 前回のすべて可能な位置を継承する
        if w > 0:
            d[h][w] |= d[h][w - 1]  # 前回のすべて可能な位置を継承する
        d[h][w] = d[h][w] << x | d[h][w] >> x
'''
今回可能な移動を記録する。
例えば前回の記録は、
00010(0,ここは最初の位置)01000で、
xは2の時、偏りは2と-2の二つ可能性がある。
ならば今回の記録は、
01000(1,ここは最初の位置)00000 | 00000(1,ここは最初の位置)00010
= 01000(1,ここは最初の位置)00010
になる。
これは、「偏りが4,0,-4の3つ可能性がある」を表示する。
最後、d[H - 1][W - 1]がすべて可能な偏りを記録したことがわかる。
'''
x, y= 1 << m, 1 << m  # 最初の「位置」で偏りが0
for i in range(m + 1):  # 最小のx,yを見つけ出す。
    if d[H - 1][W - 1] & x or d[H - 1][W - 1] & y:
        print(i)
        quit()
    x<<=1
    y>>=1
6
1
2

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
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?