Project Euler 106:Special subset sums: meta-testing 特殊的子集和:元检验
Special subset sums: meta-testing
Let S(A) represent the sum of elements in set A of size n. We shall call it a special sum set if for any two non-empty disjoint subsets, B and C, the following properties are true:
- S(B) ≠ S(C); that is, sums of subsets cannot be equal.
- If B contains more elements than C then S(B) > S(C).
For this problem we shall assume that a given set contains n strictly increasing elements and it already satisfies the second rule.
Surprisingly, out of the 25 possible subset pairs that can be obtained from a set for which n = 4, only 1 of these pairs need to be tested for equality (first rule). Similarly, when n = 7, only 70 out of the 966 subset pairs need to be tested.
For n = 12, how many of the 261625 subset pairs that can be obtained need to be tested for equality?
NOTE: This problem is related to Problem 103 and Problem 105.
记S(A)是大小为n的集合A中所有元素的和。若任取A的任意两个非空且不相交的子集B和C都满足下列条件,我们称A是一个特殊的和集:
- S(B) ≠ S(C);也就是说,任意子集的和不相同。
- 如果B中的元素比C多,则S(B) > S(C)。
在这个问题中我们假定集合中包含有n个严格单调递增的元素,并且已知其满足第二个条件。
令人惊奇的是,当n = 4时,在所有可能的25组子集对中只有1组需要检验子集和是否相等(第一个条件)。同样地,当n = 7时,在所有可能的966组子集对中只有70组需要检验。
当n = 12时,在所有可能的261625组子集对中有多少组需要检验?
解题
首先 想说的是语文差,题目没理解,搞了好久。
注意几点:
1.这里的集合和不一定是特殊子集
2.这个集合元素一定是严格递增的
3.集合是已经满足第二个条件,解题中不需要判断
4.求的是子集对可能相等的个数
4.1子集对,两个子集也一定是不相交的
4.2“需要检验”的意思是,不需要检验的子集对一定不相等,“需要检验”的子集对可能相等,注意这里面的可能 ,它也可能不相等,可以理解为:要求的是最大的个数
当 1 2 3 条都正确理解到的时候:n个数的集合只要是任意n个数的递增序列就好了,如:1、2、3、4,、、、、、、n
第4条:求子集对可能相等的个数
什么情况下两个子集B、C内元素的和是相等的?
注意:集合A是严格递增的,则子集B、C也一定是严格递增的
子集B、C元素和一定不相等的情况:
1.集合B、C的元素个数不相等
2.集合B的最小值 > 集合C的最大值
反过来
子集B、C元素和可能相等的情况:
1.集合B、C的元素个数相等 并且 B中的元素有大于C中的元素的,C中的元素有大于B中的元素的
根据上面就可解
Java
package Level4;
import java.util.ArrayList;
import java.util.Arrays; public class PE0106{ public static void run(){
int A[] = { 1,2,3,4,5,6,7,8,9,10,11,12};
// int A[] = {1219 ,1183, 1182, 1115, 1035, 1186, 591, 1197, 1167, 887, 1184, 1175};
Arrays.sort(A);
meta_testing(A); }
public static void meta_testing(int[] a){
// 所有的子集
ArrayList<ArrayList<Integer>> sets = MakeSubsets(a);
int size = sets.size();
int count_equal = 0;
int count_sets = 0;
System.out.println("子集总数量:"+size);
for(int i=0;i<size;i++){
ArrayList<Integer> set1 = sets.get(i);
for(int j=i+1;j<size;j++){
ArrayList<Integer> set2 = sets.get(j);
//不相交
if(!isDisjoint(set1,set2) ){
count_sets++;
if(set1.size() == set2.size()){
int s = 0;
int t = 0;
for(int k = 0;k<set1.size();k++){
if(set1.get(k) > set2.get(k))
s = 1;
if(set1.get(k) < set2.get(k))
t = 1; }
if(s == 1 && t == 1)
count_equal++; } }
}
}
System.out.println("子集对数量:"+count_sets);
System.out.println("可能相等的子集数量:"+count_equal);
} // 两个子集元素是否相交 true 相交 false 不相交
public static boolean isDisjoint(ArrayList<Integer> set1,ArrayList<Integer> set2){
int size1 = set1.size();
int size2 = set2.size();
ArrayList<Integer> set = new ArrayList<Integer>();
for(int i=0;i<size1;i++){
int element = set1.get(i);
if(set.contains(element))
return true;
else
set.add(element);
}
for(int i=0;i<size2;i++){
int element = set2.get(i);
if(set.contains(element))
return true;
else
set.add(element);
}
set.clear();
return false; } // 求出所有的子集
public static ArrayList<ArrayList<Integer>> MakeSubsets(int a[]){
ArrayList<ArrayList<Integer>> sets = new ArrayList<ArrayList<Integer>>();
for(int i=1;i< (int) Math.pow(2,a.length);i++){
ArrayList<Integer> set = MakeSubset(a,i);
sets.add(set);
}
return sets; }
// 求出子集
// 利用 和 1 进行与运算 并移位
// 001001 相当于根据 1 所在的位置取 第 2 第 5的位置对应的数
// &000001
//----------
// 1 取出该位置对应的数
// 下面右移一位后
// 000100
// 下面同理了
public static ArrayList<Integer> MakeSubset(int[] a,int m){
ArrayList<Integer> set = new ArrayList<Integer>();
for(int i=0;i<a.length ;i++){
if( m>0 &&(m&1)==1){
set.add(a[i]);
}
m =m>>1;
}
return set;
}
public static void main(String[] args){
long t0 = System.currentTimeMillis();
run();
long t1 = System.currentTimeMillis();
long t = t1 - t0;
System.out.println("running time="+t/1000+"s"+t%1000+"ms");
}
}
Java Code
子集总数量:4095
子集对数量:261625
可能相等的子集数量:21384
running time=3s496ms
Python
# coding=gbk
import itertools se=set(range(1,13))
c=0
for i in xrange(2,len(se)):
for m in itertools.combinations(se,i):
for n in itertools.combinations(se-set(m),i):
t=0
for k in range(len(m)):
if m[k]>n[k]:
t=1
s=0
for k in range(len(m)):
if m[k]<n[k]:
s=1
if s==1 and t==1:
c+=1
print c/2.
Mathblog 中直接求出答案,所有的子集对数量比较好求,至于后来用到了卡特兰数,问题没有过多的讲解,我也不知道为什么。
答案=
题解中看到的解答:
# coding=gbk
import itertools def C(n,k):
result = 1
for i in range(k):
result *= n - i
result /= i + 1
return result def Catalan(n):
return C(2 * n, n) / (n + 1) def e106meta(n):
result = 0
for k1 in range(1,n):
for k2 in range(1,min(k1,n-k1)+1):
x = C(n,k1)*C(n-k1,k2)
if k1 == k2:
x /= 2
result += x
return result def e106(n):
result = 0
for k in range(2,n/2 + 1):
result += C(n,2*k)*(C(2*k,k)/2 - Catalan(k))
return result if __name__ == '__main__':
assert e106(7) == 70
print e106(12)
Project Euler 106:Special subset sums: meta-testing 特殊的子集和:元检验的更多相关文章
- Project Euler P105:Special subset sums: testing 特殊的子集和 检验
Special subset sums: testing Let S(A) represent the sum of elements in set A of size n. We shall cal ...
- Project Euler 103:Special subset sums: optimum 特殊的子集和:最优解
Special subset sums: optimum Let S(A) represent the sum of elements in set A of size n. We shall cal ...
- Project Euler 44: Find the smallest pair of pentagonal numbers whose sum and difference is pentagonal.
In Problem 42 we dealt with triangular problems, in Problem 44 of Project Euler we deal with pentago ...
- Python练习题 037:Project Euler 009:毕达哥拉斯三元组之乘积
本题来自 Project Euler 第9题:https://projecteuler.net/problem=9 # Project Euler: Problem 9: Special Pythag ...
- [project euler] program 4
上一次接触 project euler 还是2011年的事情,做了前三道题,后来被第四题卡住了,前面几题的代码也没有保留下来. 今天试着暴力破解了一下,代码如下: (我大概是第 172,719 个解出 ...
- 洛谷P1466 集合 Subset Sums
P1466 集合 Subset Sums 162通过 308提交 题目提供者该用户不存在 标签USACO 难度普及/提高- 提交 讨论 题解 最新讨论 暂时没有讨论 题目描述 对于从1到N (1 ...
- Python练习题 029:Project Euler 001:3和5的倍数
开始做 Project Euler 的练习题.网站上总共有565题,真是个大题库啊! # Project Euler, Problem 1: Multiples of 3 and 5 # If we ...
- Project Euler 9
题意:三个正整数a + b + c = 1000,a*a + b*b = c*c.求a*b*c. 解法:可以暴力枚举,但是也有数学方法. 首先,a,b,c中肯定有至少一个为偶数,否则和不可能为以上两个 ...
- Codeforces348C - Subset Sums
Portal Description 给出长度为\(n(n\leq10^5)\)的序列\(\{a_n\}\)以及\(m(m\leq10^5)\)个下标集合\(\{S_m\}(\sum|S_i|\leq ...
随机推荐
- 用Swift重写公司OC项目(Day2)--创建OC与Swift的桥接文件,进而调用OC类库
昨天把项目中的图标以及启动转场图片弄好了,那么今天,我们可以开始慢慢进入到程序的编写当中了. 由于swift较新,所以类库还不够完善,但是不用担心,苹果早就出了解决方案,那就是使用桥接文件,通过桥接文 ...
- mac中添加环境变量
sudo vi /etc/paths 来编辑 paths,将环境变量添加到 paths 中. vim 是一个编辑器,另外还有几个,如:Pico,Emacs.
- 高德地图JavaScript API开发研究
高德地图JavaScript API是一套用JavaScript 语言编写的应用程序接口,可以通过各种API接口向地图添加内容,创建功能丰富.交互性强的地图应用.高德地图JavaScript API ...
- HMMPfam的安装使用手记(转载)
转载至:http://blog.sina.com.cn/s/blog_3f6403290100rb61.html(感谢原文作者) HMMPfam的安装使用手记前言 简要介绍一下 HMMPfam吧.这还 ...
- Labview实现脉波调制( PAM )
Labview实现脉波调制( PAM ) 根据定义为脉冲振幅调制 生成一个正弦信号,得到其幅值输入给一个方波信号的幅值 这个等价于一个方波信号和一个正弦信号相乘 得到的PAM信号通过观察其频率可以发现 ...
- QT 十六进制字符串转化为十六进制编码
/*************************************************Function: hexStringtoByteArray()Description: 十六进制字 ...
- Valuable site on github
https://thegrid.io/?utm_source=adwords&utm_medium=cpc&utm_campaign=thegrid-display-english&a ...
- cocos2dx 2.0+ 版本,IOS6.0+设置横屏
使用cocos2dx 自带的xcode模板,是不能正常的设置为横屏的. 一共修改了三个地方: 在项目属性中:Deployment Info中,勾选上 Landscape left,以及 Landsca ...
- 四则运算(2)之软件单元测试:Right-BICEP
一.Right-BICEP主要测试以下几方面的问题: Right-结果是否正确? B-是否所有的边界条件都是正确的? I-能查一下反向关联吗? C-能用其他手段交叉检查一下结果吗? E-你是否可以强制 ...
- LNMP系列网站零基础开发记录(一)
[目录] 扯淡吹逼之开发前奏 Django 开发环境搭建及配置 web 页面开发 Django app开发 Django 站点管理 Python 简易爬虫开发 Nginx&uWSGI 服务器配 ...