package main import ( "bufio" "fmt" "os" "sort" ) const MAX = 60000 + 1 // a+b 最大 60000 var isPrime [MAX]bool // 线性筛法预处理素数 func sieve() { // 从2开始,先初始化为都是素数 for i:=2;i<MAX;i++{ isPrime[i] = true } for i:=2;i<MAX;i++{ if isPrime[i] { for j:= i*i;j<MAX;j+=i{ // 素数的倍数不是素数 isPrime[j] = false } } } } /* 素数是奇数+偶数 二分图配对问题 以个数少的一方为配对基准(左图left) 优先对left中可匹配right图数较少的元素进行配对 步骤: 1)素数集求解 2)读取数据 3)奇偶分离(二分) 4)可配对情况 邻接表adj 5)尝试配对 函数dfs —— 匈牙利算法 6)开始配对,并输出结果 */ func main() { /* 1)素数集求解 */ sieve() /* 2)读取数据 */ scanner := bufio.NewScanner(os.Stdin) scanner.Split(bufio.ScanWords) // 读 n scanner.Scan() var n int fmt.Sscan(scanner.Text(), &n) // 读 n 个数 nums := make([]int, n) for i := 0; i < n; i++ { scanner.Scan() fmt.Sscan(scanner.Text(), &nums[i]) } /* 3)奇偶分离(二分) */ // 分离奇偶 var odds, evens []int for i:=0;i<n;i++{ if nums[i]%2 ==0{ evens =append(evens, nums[i]) }else{ odds = append(odds, nums[i]) } } // 决定哪边做左部(如果个数相差较大):选个数少的 evensLessOdd := float64((len(odds) - len(evens)))/float64(len(evens)) > 0.2 var left, right []int var adj [][]int if evensLessOdd { left, right = evens, odds } else { left, right = odds, evens } /* 4)可配对情况 邻接表adj */ // 构建邻接表:left[i] 能和哪些 right[j] 配对 adj = make([][]int, len(left)) // 记录left和right中元素的索引,而非数值 var t int for i:= 0;i<len(left);i++{ for j:=0;j<len(right);j++{ t = left[i]+right[j] if t < MAX && isPrime[t] { adj[i] = append(adj[i], j) } } } // (可选,由于一般相差不大,排序未必更高效)在构建 adj 后,按可匹配数升序排序 left indices := make([]int, len(left)) for i := range indices { indices[i] = i } sort.Slice(indices, func(i, j int) bool { return len(adj[indices[i]]) < len(adj[indices[j]]) }) // 重新排序 adj(和 left,如果需要) newAdj := make([][]int, len(left)) for i, idx := range indices { newAdj[i] = adj[idx] } adj = newAdj /* 5)尝试配对 函数dfs */ // 匈牙利算法求最大匹配 matchRight := make([]int, len(right)) // matchRight[j] = 哪个 left 的索引匹配了 right[j] for i:=0;i<len(matchRight);i++{ matchRight[i] = -1 // -1 表示未匹配 } var dfs func(u int, visited []bool) bool dfs = func(u int, visited []bool) bool { for _, i := range adj[u] { if visited[i]{ continue } visited[i] = true if matchRight[i] == -1 || dfs(matchRight[i], visited) { matchRight[i] = u return true } } return false } /* 6)开始配对,并输出结果 */ var matching int =0 for i:=0;i<len(left);i++ { visited := make([]bool, len(right)) if dfs(i, visited){ matching++ } } fmt.Println(matching) }