2021.04.01手链样式

本文通过一个实例介绍了如何计算具有旋转和翻转因素的手链不同组合样式。利用组合数学和回文判断,解决奇数和偶数元素共存情况下的翻转问题。最后提供了一段代码实现,用于暴力枚举所有可能的组合。

2021.04.01手链样式

题目描述

小明有3颗红珊瑚,4颗白珊瑚,5颗黄玛瑙。
他想用它们串成一圈作为手链,送给女朋友。
现在小明想知道:如果考虑手链可以随意转动或翻转,一共可以有多少不同的组合样式呢?

思路

组合数学

  1. 如果不考虑环、不考虑翻转,则共有 t=(5+4+3)!5!∗4!∗3!t=\frac{(5+4+3)!}{5!*4!*3!}t=5!4!3!(5+4+3)!
  2. 如果考虑环,则有 t=t/12
  3. 如果考虑翻转
    1. 假设翻转后相同的有x个,则除去翻转前有t个,除去翻转后共有t−x2+x\frac{t-x}{2}+x2tx+x个。
    2. 这里的翻转指的是将手链对折,由于红珊瑚和黄都是奇数个,所以在对折线上的必是红和黄,还剩RR WWWW YYYY,对于R WW YY共有5!2!∗2!=30\frac{5!}{2!*2!}=302!2!5!=30种不同排列。

所以答案为(5+4+3)!5!∗4!∗3!12−302−30=2170\frac{\frac{\frac{(5+4+3)!}{5!*4!*3!}}{12}-30}{2}-30 = 21702125!4!3!(5+4+3)!3030=2170

暴力

  1. 判断是否在转动后属于一种情况。

例子:
有字符串: a: “rwy” b: “wyr”,构造字符串 S = a+a: “rwyrwy”,如果b是S的子串,说明a和b转动属于一种情况。

  1. 判断是否在翻转后属于一种情况。

由于是沿着中心轴翻转,所以奇数个和偶数个元素情况是不同的,只考虑偶数个元素的情况。可以举例证得,翻转后的序列在转动后刚好是原序列的你序列。

所以,如果S在翻转后仍包含子序列b,说明a和b在翻转后属于一种情况。

代码

	ArrayList<String> lis = new ArrayList<String>();
	String s = "aaabbbbccccc";
	
	boolean match(String a, String b) {
		String S = a+a;
		//考虑转动
		if(S.indexOf(b)>0) return true;
		//考虑翻转,即回文相等
		StringBuffer sb = new StringBuffer();
		for(int i = S.length()-1; i >= 0; i--) sb.append(S.charAt(i));
		if(sb.toString().indexOf(b)>0) return true;
		return false;
	}
	
	boolean has(String a) {
		for(String s: lis) if(match(s, a)) return true;
		return false;
	}
	
	void dfs(char[] a, int beg, int end) {
		if(beg == end) {
			String str = new String(a);
			if(!has(str)) {
				lis.add(str);
			}
		}
		else {
			for(int i = beg; i < end; i++) {
				char t = a[i]; a[i] = a[beg]; a[beg] = t;
				dfs(a, beg+1, end);
				t = a[i]; a[i] = a[beg]; a[beg] = t;
			}
		}
	}
	
	void test3() {
		dfs(s.toCharArray(), 0, s.length());
		System.out.println(lis.size());
	}
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值