TopCoder SRM DIV2 Level 3: RelativelyPrimeSubset
2013-06-30 20:56
441 查看
题目: http://community.topcoder.com/stat?c=problem_statement&pm=12074&rd=14739
题目大意: 给定n个正整数,从其中选取k个数使得集合中所有数互素。 求k的最大值。
例子: {2,3,7,11,4}, 最大互素集合为{2,3,7,11} 和 {3,7,11,4},所以集合个数为4。
范围: 1<=n<=50, 集合中元素最大值不超过100.
求解:第一反应这是个典型的0-1背包问题,采用动态规划求解. dp[i, mask]表示第i个元素时, 集合中素数的位信息为mask时,集合的大小。
递推式: dp[i, mask] = max {dp[i-1, mask'] + 1, dp[i-1, mask]} (s[i]符合mask条件), 其中mask' = mask ^ GetMask(s[i]); 如果s[i]与mask不符合, 表示s[i]的某个素数因子在mask中位信息为1,但mask在这一位为0 ,这种mask情况下, 第i个元素不能被选中, dp[i, mask] = dp[i-1, mask].
初始值, s[0]=p1^e1*p2^e2*,,,*pk^ek, 则dp[0, e1e2...ek] = 1, 其余都为0.
时间复杂度分析, 俨然该算法的时间复杂度为O(n*2^k), 100以内的素数有25个,则该算法时间复杂度为O(50 * 2^25), 2^25 大概在千万级别(25*log2 = 7.5),时间复杂度略高。
后来看解题报告才知,这里有个小技巧: 如果元素大于50且为素数,那么它必定在最大互素集合中。why? 因为该素数要么就是自己, 它组成的合数必然大于100,是不会在集合中出现的。 那么可以将k减小至小于50的素数个数, 总共有15个。时间复杂度将为O(50*2^15)。不超过6位数。
C# Code
题目大意: 给定n个正整数,从其中选取k个数使得集合中所有数互素。 求k的最大值。
例子: {2,3,7,11,4}, 最大互素集合为{2,3,7,11} 和 {3,7,11,4},所以集合个数为4。
范围: 1<=n<=50, 集合中元素最大值不超过100.
求解:第一反应这是个典型的0-1背包问题,采用动态规划求解. dp[i, mask]表示第i个元素时, 集合中素数的位信息为mask时,集合的大小。
递推式: dp[i, mask] = max {dp[i-1, mask'] + 1, dp[i-1, mask]} (s[i]符合mask条件), 其中mask' = mask ^ GetMask(s[i]); 如果s[i]与mask不符合, 表示s[i]的某个素数因子在mask中位信息为1,但mask在这一位为0 ,这种mask情况下, 第i个元素不能被选中, dp[i, mask] = dp[i-1, mask].
初始值, s[0]=p1^e1*p2^e2*,,,*pk^ek, 则dp[0, e1e2...ek] = 1, 其余都为0.
时间复杂度分析, 俨然该算法的时间复杂度为O(n*2^k), 100以内的素数有25个,则该算法时间复杂度为O(50 * 2^25), 2^25 大概在千万级别(25*log2 = 7.5),时间复杂度略高。
后来看解题报告才知,这里有个小技巧: 如果元素大于50且为素数,那么它必定在最大互素集合中。why? 因为该素数要么就是自己, 它组成的合数必然大于100,是不会在集合中出现的。 那么可以将k减小至小于50的素数个数, 总共有15个。时间复杂度将为O(50*2^15)。不超过6位数。
C# Code
using System; using System.Collections.Generic; using System.Text; class RelativelyPrimeSubset { public int findSize(int[] S) { List<int> primes = new List<int>(); bool[] isPrimes = new bool[101]; for (int i = 2; i <= 100; i++) { if (IsPrime(i)) { primes.Add(i); isPrimes[i] = true; } else { isPrimes[i] = false; } } List<int> list = new List<int>(); int cnt = 0; foreach(int a in S) { if (isPrimes[a] && a > 50) { cnt++; } else { list.Add(a); } } S = list.ToArray(); int n = S.Length; int m = (1 << 16) + 1; int[,] dp = new int[101, m]; for (int i = 0; i < m; i++) { dp[0, i] = 0; } dp[0, GetMask(primes, S[0])] = 1; int mask_max = 1 << 16; for (int i = 1; i < n; i++) { int x = S[i]; int x_mask = GetMask(primes, x); for (int mask = 0; mask < mask_max; mask++) { if (IsValidation(mask, x_mask)) { int c = mask & (~x_mask); int a = dp[i - 1, mask]; if (dp[i - 1, c] + 1 > a) { a = dp[i-1, c] + 1; } dp[i, mask] = a; } else { dp[i, mask] = dp[i-1, mask]; } } } int max = 0; for(int mask = 0; mask <m; mask ++) { if (dp[n-1, mask] > max) { max= dp[n-1, mask]; } } return max + cnt; } // mask1 contain mask2 private static bool IsValidation(int mask1, int mask2) { int x = mask1; int y = mask2; while (true) { int p1 = x % 2; int p2 = y % 2; if (p1 == 0 && p2 == 1) { return false; } x = x / 2; y = y / 2; if (x == 0 || y == 0) { break; } } if (x == 0 && y > 0) { return false; } return true; } private static int GetMask(List<int> primes, int x) { int mask = 0; for (int i = 0; i < primes.Count; i++) { if (x % primes[i] == 0) { mask |= (1 << i); x = x / primes[i]; } } return mask; } private static bool IsPrime(int n) { if (n == 2) { return true; } for (int i = 2; i * i <= n; i++) { if (n % i == 0) { return false; } } return true; } }
相关文章推荐
- RelativelyPrimeSubset(SRM547-div-2-3)
- Find the number of subsets such that the sum of numbers in the subset is a prime number
- SDOI DAY1 T1 & CodeChef Divisible Subset 前缀和抽屉原理
- POJ-2689-Prime Distance
- 吴恩达 深度学习 编程作业(5-1)Part 2 - Character level language model - Dinosaurus land
- eclipse 报错 Java compiler level does not match the version of the installed Java project facet.
- POJ-1811-Prime Test
- 关于迁移学习的high level理解
- Binary Tree Zigzag Level Order Traversal
- PAT (Advanced Level) 1089. Insert or Merge (25)
- java compiler level does not match the version of the installed java project
- PAT Advanced Level 1086. Tree Traversals Again (25)(Java and C++)
- PAT (Advanced Level) 1095. Cars on Campus (30)
- PAT乙级(Basic Level)真题-1007 A除以B (20)
- POJ2689 Prime Distance
- poj3262 Prime Path 素数打表+bfs
- PAT乙级(Basic Level)真题-1028 统计同成绩学生(20)
- Leetcode: Binary Tree Level Order Transversal II
- SqueezeNet: AlexNet-level accuracy with 50x fewer parameters and <1MB model size阅读笔记
- PAT (Advanced Level)1121. Damn Single (25)第二个测 4000 试点过不去,求助