yukicoder contest 245 参戦記
A 1033 乱数サイ
問題を見た瞬間に、K ってなんのためにあるんだろうと思ったが、やっぱり要らなかった(笑). 0~Nの平均値は0~Nの合計値をN+1で割ったものなので (0 + N) * (N + 1) ÷ 2 ÷ (N + 1) なので、N ÷ 2 となる.
N, K = map(int, input().split())
print(N / 2)
D 1036 Make One With GCD 2
セグ木の GCD 版を持っていたので瞬殺だった(笑). 基本は尺取法. GCD が1になったらそこから先はどれだけ進めても1なので、GCD(Ai, Ai+1, ..., Aj) で初めて1になったのであれば、Aiを左端とする部分列で GCD が1になる部分列の数は N - j + 1 となる. 次は Ai+1 を左端とする部分列を考えるのだが、当然右端は j 以上の数となる. ここで GCD(Ai+1, ..., Aj) を高速に計算するためにセグ木を使った. なお、j が N になっても GCD が1にならなかったら、それより右側の部分列では GCD は1にならないので、そこで計算を打ち切って良い.
package main
import (
	"bufio"
	"fmt"
	"os"
	"strconv"
)
func gcd(a, b int) int {
	if a < b {
		a, b = b, a
	}
	for b > 0 {
		a, b = b, a%b
	}
	return a
}
type segmentTree struct {
	data   []int
	offset int
}
func newSegmentTree(n int) segmentTree {
	var result segmentTree
	t := 1
	for t < n {
		t *= 2
	}
	result.offset = t - 1
	result.data = make([]int, 2*t-1)
	return result
}
func (st segmentTree) updateAll(a []int) {
	for i, v := range a {
		st.data[st.offset+i] = v
	}
	for i := st.offset - 1; i > -1; i-- {
		st.data[i] = gcd(st.data[i*2+1], st.data[i*2+2])
	}
}
func (st segmentTree) update(index, value int) {
	i := st.offset + index
	st.data[i] = value
	for i >= 1 {
		i = (i - 1) / 2
		st.data[i] = gcd(st.data[i*2+1], st.data[i*2+2])
	}
}
func (st segmentTree) query(start, stop int) int {
	result := 0
	l := start + st.offset
	r := stop + st.offset
	for l < r {
		if l&1 == 0 {
			result = gcd(result, st.data[l])
		}
		if r&1 == 0 {
			result = gcd(result, st.data[r-1])
		}
		l = l / 2
		r = (r - 1) / 2
	}
	return result
}
func main() {
	defer flush()
	N := readInt()
	A := make([]int, N)
	for i := 0; i < N; i++ {
		A[i] = readInt()
	}
	st := newSegmentTree(N)
	st.updateAll(A)
	result := 0
	j := 1
	for i := 0; i < N; i++ {
		v := st.query(i, j)
		for v != 1 && j < N {
			v = gcd(v, A[j])
			j++
		}
		if v != 1 {
			break
		}
		result += N - j + 1
	}
	println(result)
}
const (
	ioBufferSize = 1 * 1024 * 1024 // 1 MB
)
var stdinScanner = func() *bufio.Scanner {
	result := bufio.NewScanner(os.Stdin)
	result.Buffer(make([]byte, ioBufferSize), ioBufferSize)
	result.Split(bufio.ScanWords)
	return result
}()
func readString() string {
	stdinScanner.Scan()
	return stdinScanner.Text()
}
func readInt() int {
	result, err := strconv.Atoi(readString())
	if err != nil {
		panic(err)
	}
	return result
}
func readInts(n int) []int {
	result := make([]int, n)
	for i := 0; i < n; i++ {
		result[i] = readInt()
	}
	return result
}
var stdoutWriter = bufio.NewWriter(os.Stdout)
func flush() {
	stdoutWriter.Flush()
}
func printf(f string, args ...interface{}) (int, error) {
	return fmt.Fprintf(stdoutWriter, f, args...)
}
func println(args ...interface{}) (int, error) {
	return fmt.Fprintln(stdoutWriter, args...)
}
B 1034 テスターのふっぴーさん
時計回りに渦を巻きながら進んでいくわけだが、(I, J) が何巻目かをまず考える. I, J, N - 1 - I, N - 1 - J の最小値だと分かる. この最小値を l すると、l 巻目に入るまでに移動した回数は、全移動回数 N * N から、l 巻以降の移動回数 (N - 2 * l) * (N - 2 * l) を引いたものだと分かる. 後は一巻きだけ進めてかかった移動を確認し、l巻き目に入るまで移動した回数と合算すれば回答できる.
Q = int(input())
for i in range(Q):
    N, I, J = map(int, input().split())
    l = min(I, J, N - 1 - I, N - 1 - J)
    result = N * N - (N - 2 * l) * (N - 2 * l)
    N, I, J = N - 2 * l, I - l, J - l
    if I == 0:
        result += J
    elif J == N - 1:
        result += N - 1 + I
    elif I == N - 1:
        result += 2 * (N - 1) + (N - 1) - J
    elif J == 0:
        result += 3 * (N - 1) + (N - 1) - I
    print(result)
E 1037 exhausted
println(result) を print(result) と書いてしまって、コンテスト中に回答できなかった orz. 全く同じアルゴリズムで Python で書いたら、WA は出なかったものの TLE したので Go 言語で書き直している.
ガソリンスタンドに着くたびに、燃料を入れるパターンと入れないパターンの DP をするだけなので、特に難しいことはないんじゃなかろうか. 同じ燃料の量でそこまでの費用が高い場合はそのパターンを捨てる.
package main
import (
	"bufio"
	"fmt"
	"math"
	"os"
	"strconv"
)
func min(a, b int) int {
	if a < b {
		return a
	}
	return b
}
func main() {
	defer flush()
	N := readInt()
	V := readInt()
	L := readInt()
	cx := 0
	d := map[int]int{}
	d[V] = 0
	for i := 0; i < N; i++ {
		x := readInt()
		v := readInt()
		w := readInt()
		nd := map[int]int{}
		for k := range d {
			t := k - (x - cx)
			if t < 0 {
				continue
			}
			_, ok := nd[t]
			if !ok || nd[t] > d[k] {
				nd[t] = d[k]
			}
			t = min(t+v, V)
			_, ok = nd[t]
			if !ok || nd[t] > d[k]+w {
				nd[t] = d[k] + w
			}
		}
		if len(nd) == 0 {
			println(-1)
			return
		}
		d = nd
		cx = x
	}
	result := math.MaxInt64
	for k := range d {
		if k-(L-cx) >= 0 {
			result = min(result, d[k])
		}
	}
	println(result)
}
const (
	ioBufferSize = 1 * 1024 * 1024 // 1 MB
)
var stdinScanner = func() *bufio.Scanner {
	result := bufio.NewScanner(os.Stdin)
	result.Buffer(make([]byte, ioBufferSize), ioBufferSize)
	result.Split(bufio.ScanWords)
	return result
}()
func readString() string {
	stdinScanner.Scan()
	return stdinScanner.Text()
}
func readInt() int {
	result, err := strconv.Atoi(readString())
	if err != nil {
		panic(err)
	}
	return result
}
func readInts(n int) []int {
	result := make([]int, n)
	for i := 0; i < n; i++ {
		result[i] = readInt()
	}
	return result
}
var stdoutWriter = bufio.NewWriter(os.Stdout)
func flush() {
	stdoutWriter.Flush()
}
func printf(f string, args ...interface{}) (int, error) {
	return fmt.Fprintf(stdoutWriter, f, args...)
}
func println(args ...interface{}) (int, error) {
	return fmt.Fprintln(stdoutWriter, args...)
}
C 1035 Color Box
i種類のペンキを使って色を塗る塗り方の総数を f(i) とすると、f(i) = MCi * iN - f(i - 1) となる. また、f(0) = 0 である.
と簡潔に書いていますが、これにたどり着くのに5時間以上かかりました orz. ★2個とか嘘やろ.
from sys import setrecursionlimit
setrecursionlimit(1000000)
N, M = map(int, input().split())
fac = [0] * (M + 1)
fac[0] = 1
for i in range(M):
    fac[i + 1] = fac[i] * (i + 1) % 1000000007
def mcomb(n, k):
    if n == 0 and k == 0:
        return 1
    if n < k or k < 0:
        return 0
    return fac[n] * pow(fac[n - k], 1000000005, 1000000007) * pow(fac[k], 1000000005, 1000000007) % 1000000007
def f(i):
    if i == 0:
        return 0
    return (mcomb(M, i) * pow(i, N, 1000000007) - f(i - 1)) % 1000000007
print(f(M))