- T1
一个数的十进制表示若只有1,0则称这个数是quasibinary,给定一个正整数n(1 ≤ n ≤ 10e6),把它表示成最少个数quasibinary的和。
input
9
output
9
1 1 1 1 1 1 1 1 1
input
32
output
3
10 11 11
解:
对一个n,如5203,每一位若不是0,给一个1,否则给0,
5203 - 1101 = 4102
4102 - 1101 = 3001
3001 - 1001 = 2000
2000 - 1000 = 1000
2000 - 1000 = 0
则 5203 = 1101 + 1101 + 1001 + 1000 + 1000
code(go):
package main
import (
"fmt"
"strconv"
)
func main() {
var n int
fmt.Scan(&n)
k := 0
ans := ""
for n != 0 {
cur := n
m := 0
p := 1
for cur != 0 {
if cur%10 != 0 {
m += p
}
p *= 10
cur /= 10
}
k++
n -= m
ans += strconv.Itoa(m)
ans += " "
}
fmt.Println(k)
fmt.Println(ans)
}
- T2(617B)
0, 1组成的序列,拆分称若干组,没组和为1,有多少拆分法?
Examples
input
3
0 1 0
output
1
input
5
1 0 1 0 1
output
4
相邻两个1之间有多少个数,这一段就有多少种不同的组合。
代码(python3)
import sys
n = int(input())
an = list(map(int, sys.stdin.readline().split()))
ans = 0
pre = 0
for i in range(n):
if an[i] is 1:
if ans is 0:
ans = 1
else:
ans *= (i - pre)
pre = i
print(ans)
- T3(574A)
序列an,每次操作可使任一个数减1,an[0]加1,最少多少次操作可使an[0]变为最大数?
Examples
input
5
5 1 11 2 8
output
4
input
4
1 8 8 8
output
6
input
2
7 6
output
0
每次操作找到序列中最大值减1,an[0]加1即可。
代码(python3):
import sys
n = int(input())
an = list(map(int, sys.stdin.readline().split()))
ans = 0
while True:
max_i = 0
for i in range(1, n):
if an[i] >= an[max_i]:
max_i = i
if max_i is 0:
break
else:
an[0] += 1
an[max_i] -= 1
ans += 1
print(ans)
- T4(115A)
Examples
input
5
-1
1
2
1
-1
output
3
第一行为人数n,后面n行表示第i个人的直接领导,-1表示没有直接领导。
现在要组织一个活动,要求分成若干组,每个组中不能存在领导关系,求最小组数。
解:
例子给出的领导关系为:
1->2->3
4->1
5
则最少组数为最长的领导链长度3
package main
import (
"fmt"
)
func main() {
var n int
fmt.Scan(&n)
pn := make([]int, n+1, n+1)
for i := 0; i < n; i++ {
fmt.Scan(&pn[i])
}
ans := 0
for i := 0; i < n; i++ {
depth := 1
cur := pn[i]
for cur != -1 {
cur = pn[cur-1]
depth++
}
if ans < depth {
ans = depth
}
}
fmt.Println(ans)
}
- T5(567B)
Examples
input
6
+ 12001
- 12001
- 1
- 1200
+ 1
+ 7
output
3
input
2
- 1
- 2
output
2
input
2
+ 1
- 1
output
1
第一行为记录数n,后面n行表示n条记录,
+ x 表示编号为x的人进入
- x 表示编号为x的人离开
我们开始记录的时候可能已经有人在,求最小容量。
解:
我们记录当前已经进来了cur个人,in[x]表示x是否已进入
当+x,一个人进入时,in[x]=true, cur++, 若cur > ans, ans=cur
当-x,一个人离开时,若in[x],即这个人已记录进来了,cur–
若in[x]==false,表示这个人在开始记录前已进来,ans++
并标记这个人离开,in[x]=false
package main
import (
"bufio"
"fmt"
"os"
"strconv"
)
func main() {
var n int
fmt.Scan(&n)
in := make([]bool, 1000001, 1000001)
cur := 0
ans := 0
bs := bufio.NewScanner(os.Stdin)
bs.Split(bufio.ScanWords)
for i := 0; i < n; i++ {
bs.Scan()
c := bs.Text()[0]
bs.Scan()
p, _ := strconv.Atoi(bs.Text())
if c == '+' {
in[p] = true
cur++
if ans < cur {
ans = cur
}
} else {
if in[p] == true {
cur--
} else {
ans++
}
in[p] = false
}
}
fmt.Println(ans)
}
- T6(556B)
Examples
input
3
1 0 0
output
Yes
input
5
4 2 1 4 3
output
Yes
input
4
0 2 3 1
output
No
一个机器,有n个数(0 ~ n-1),按一次按钮,第一个数+1,第二个-1,第三个+1…, (0-1 = n-1, n-1 + 1 = 0)
问能不能按若干次按钮,使这些数变成0, 1, 2…
如第一个例子,
1,0,0 -> 2, 2, 1
2, 2, 1 -> 0, 1, 2
解:
1) 按n次后会回归初始状态,所以可以有O(n*n)方法,模拟n次按按钮操作
2) 可以确定第一个数需要按按钮次数,检测后面的数是否变成正确的数O(n)
代码(GO)
package main
import (
"fmt"
)
func main() {
var n int
fmt.Scan(&n)
an := make([]int, n, n)
for i := 0; i < n; i++ {
fmt.Scan(&an[i])
}
first := n - an[0]
ans := true
for i := 1; i < n; i++ {
if i%2 != 0 {
an[i] -= first
an[i] += n
} else {
an[i] += first
}
if an[i]%n != i {
ans = false
break
}
}
if ans {
fmt.Println("Yes")
} else {
fmt.Println("No")
}
}
- T7(588B)
Examples
input
10
output
10
input
12
output
6
给定数n,寻找一个数x,满足:
1> n % x == 0
2> x % (i*i) != 0 (i = 1, 2…)
n可以分解为若干质数pi
则x = p1*p2*…*pk
package main
import (
"fmt"
)
func main() {
var n uint64
fmt.Scan(&n)
var i, ans uint64
i = 2
ans = 1
for i*i <= n {
if n%i == 0 {
ans *= i
for n%i == 0 {
n /= i
}
}
i++
}
if n > 1 {
ans *= n
}
fmt.Println(ans)
}
- T8(559A)
Examples
input
1 1 1 1 1 1
output
6
input
1 2 1 2 1 2
output
13
给出6个数,组成一个内角都为120度的六边形(保证能组成),
求能分成多少个边长为1的正三角形。
如:
解:
可以拆分如下:
假设六条边为a1~a6, 则可构造一个边长为(a1+a2+a3)的正三角形,
import sys
an = list(map(int, sys.stdin.readline().split()))
ans = (an[0] + an[1] + an[2])*(an[0] + an[1] + an[2]) - an[0]*an[0] - an[2]*an[2] - an[4] * an[4]
print(ans)
- T9(508A)
Examples
input
2 2 4
1 1
1 2
2 1
2 2
output
4
input
2 3 6
2 3
2 2
1 3
2 2
1 2
1 1
output
5
input
5 3 7
2 3
1 2
1 1
4 1
3 1
5 3
3 2
output
0
第一行n, m, k表示一个矩阵的行列,及操作步数,
后面k行x, y会把矩阵x, y位置置为1,若第x步,矩阵出现2x2方格数字都为1,则失败,
求第几步失败,若每失败输出0.
设置一个(n+2) * (m+2)的矩阵,逐步检测是否出现2*2都为1的方格。
代码(GO),二维切片
package main
import (
"bufio"
"fmt"
"os"
"strconv"
)
func is_lose(img [][]int, x, y int) bool {
ret := false
if img[x-1][y-1]+img[x-1][y]+img[x][y-1]+img[x][y] == 4 {
ret = true
} else if img[x-1][y+1]+img[x-1][y]+img[x][y+1]+img[x][y] == 4 {
ret = true
} else if img[x+1][y-1]+img[x+1][y]+img[x][y-1]+img[x][y] == 4 {
ret = true
} else if img[x+1][y+1]+img[x+1][y]+img[x][y+1]+img[x][y] == 4 {
ret = true
}
return ret
}
/*
func dump(img [][]int, n, m int) {
for i := 0; i < n+2; i++ {
for j := 0; j < m+2; j++ {
fmt.Printf("%d ", img[i][j])
}
fmt.Println()
}
}
*/
func main() {
var n, m, k int
fmt.Scan(&n, &m, &k)
img := [][]int{}
for i := 0; i <= n+1; i++ {
row := make([]int, m+2, m+2)
img = append(img, row)
}
ans := 0
bs := bufio.NewScanner(os.Stdin)
bs.Split(bufio.ScanWords)
for i := 0; i < k; i++ {
bs.Scan()
x, _ := strconv.Atoi(bs.Text())
bs.Scan()
y, _ := strconv.Atoi(bs.Text())
img[x][y] = 1
//dump(img, n, m)
if is_lose(img, x, y) {
ans = i + 1
break
}
}
fmt.Println(ans)
}
- T10(219A)
一个字符串s,若能分成k个完全相关的字符串,则称为k-string.
如 “aabaabaabaab” 是1-string, 2-string, 4-string, 不是3-string, 5-string, 6-string…
给一个字符串s和数字k,问修改s的顺序,是否可组成k-string.
若能,输出字符串,否则输出-1
Examples
input
2
aazz
output
azaz
input
3
abcabcabz
output
-1
解:
1)计数每个字母出现的个数
2)若一个字母出现x次,x不能整除k,则不能组成k-string,否则这个字符串将被分成k份,
每份有cnt/k个这个字母
package main
import (
"fmt"
)
func solve(k int, s string) string {
length := len(s)
if length%k != 0 {
return "-1"
}
counts := make([]int, 26, 26)
for i := 0; i < length; i++ {
counts[s[i]-'a']++
}
tmp := ""
for i := 0; i < 26; i++ {
if counts[i] == 0 {
continue
}
if counts[i]%k != 0 {
return "-1"
}
for j := 0; j < counts[i]/k; j++ {
tmp += string(i + 'a')
}
}
ans := ""
for i := 0; i < length/len(tmp); i++ {
ans += tmp
}
return ans
}
func main() {
var k int
fmt.Scan(&k)
var s string
fmt.Scan(&s)
fmt.Println(solve(k, s))
}