結果
| 問題 |
No.1782 ManyCoins
|
| コンテスト | |
| ユーザー |
|
| 提出日時 | 2024-09-08 23:36:54 |
| 言語 | Go (1.23.4) |
| 結果 |
AC
|
| 実行時間 | 681 ms / 2,000 ms |
| コード長 | 2,120 bytes |
| コンパイル時間 | 13,379 ms |
| コンパイル使用メモリ | 235,744 KB |
| 実行使用メモリ | 11,864 KB |
| 最終ジャッジ日時 | 2024-09-08 23:37:15 |
| 合計ジャッジ時間 | 18,040 ms |
|
ジャッジサーバーID (参考情報) |
judge3 / judge2 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 3 |
| other | AC * 48 |
ソースコード
package main
import (
"bufio"
"fmt"
"os"
)
func main() {
P2371()
}
// P2371 [国家集训队] 墨墨的等式
// https://www.luogu.com.cn/problem/P2371
// No.1782 ManyCoins
// https://yukicoder.me/submissions/1008663
// 给定n个系数coeffs和上下界lower,upper
// !对于 lower<=k<=upper 求有多少个k能够满足
// !a0*x0+a1*x1+...+an*xn=k
// n<=12 0<=ai<=5e5 1<=lower<=upper<=2^63-1
// !时间复杂度:O(n*ai)
func P2371() {
in := bufio.NewReader(os.Stdin)
out := bufio.NewWriter(os.Stdout)
defer out.Flush()
var n, lower, upper int
fmt.Fscan(in, &n, &upper)
lower = 1
coeffs := make([]int, n)
for i := 0; i < n; i++ {
fmt.Fscan(in, &coeffs[i])
}
retain(&coeffs, func(i int) bool { return coeffs[i] != 0 })
if len(coeffs) == 0 {
fmt.Fprintln(out, 0)
return
}
base, dp := ModShortestPath(coeffs)
res := 0
for i := range base {
if upper >= dp[i] {
res += (upper-dp[i])/base + 1
}
if lower > dp[i] {
res -= (lower-1-dp[i])/base + 1
}
}
fmt.Fprintln(out, res)
}
const INF int = 1e18
func ModShortestPath(coeffs []int) (int, []int) {
coeffs = append(coeffs[:0:0], coeffs...)
retain(&coeffs, func(i int) bool { return coeffs[i] > 0 })
if len(coeffs) == 0 {
return 0, nil
}
base := mins(coeffs...)
dp := make([]int, base)
for i := range dp {
dp[i] = INF
}
dp[0] = 0
for _, v := range coeffs {
cycle := gcd(base, v)
for j := 0; j < cycle; j++ {
for cur, count := j, 0; count < 2; {
next := (cur + v) % base
dp[next] = min(dp[next], dp[cur]+v)
cur = next
if cur == j {
count++
}
}
}
}
return base, dp
}
func gcd(a, b int) int {
for b != 0 {
a, b = b, a%b
}
return a
}
func min(a, b int) int {
if a < b {
return a
}
return b
}
func max(a, b int) int {
if a > b {
return a
}
return b
}
func mins(nums ...int) int {
res := nums[0]
for _, num := range nums {
if num < res {
res = num
}
}
return res
}
func retain(arr *[]int, f func(index int) bool) {
ptr := 0
n := len(*arr)
for i := 0; i < n; i++ {
if f(i) {
(*arr)[ptr] = (*arr)[i]
ptr++
}
}
*arr = (*arr)[:ptr:ptr]
}