复(学)习化学时突然的一个 idea

期中考试成功探底。。。但是某些化学问题还是很有信息学价值的。。。

n 烷同分异构体计数。

这个题 fanhq666 出过,就是一个 dp。

设 f[i] 表示含有 i 个节点的无标号不同构的度数限制为 4 的有根树的个数。那么转移时枚举最多 3 个子树的大小,如果大小相同时用组合数,否则乘法原理就好了。

最后统计答案时找到中心为根,然后最多 4 个子树,每个大小不超过 [n / 2] - 1(除法取上整),同样的累计方法(组合数/乘法原理)统计一下就好了;双重心时需要把两个重心同时提上去统计一遍和刚才的答案累加。

没事闲的写了个比较全的高精度,先贴高精度模板。

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cctype>
#include <algorithm>
using namespace std;

int read() {
	int x = 0, f = 1; char c = getchar();
	while(!isdigit(c)){ if(c == ‘-‘) f = -1; c = getchar(); }
	while(isdigit(c)){ x = x * 10 + c - ‘0‘; c = getchar(); }
	return x * f;
}

struct LL {
	int len, A[5010];

	LL() { len = -1; }
	LL(int x) {
		A[1] = x; len = 1;
		if(x) while(A[len] > 9) A[len+1] = A[len] / 10, A[len] %= 10, len++;
		else len = -1;
	}

	LL operator = (const int& t) {
		A[1] = t; len = 1;
		if(t) while(A[len] > 9) A[len+1] = A[len] / 10, A[len] %= 10, len++;
		else len = -1;
		return *this;
	}

	LL operator + (const LL& t) const {
		LL ans; ans.len = max(len, t.len);
		for(int i = 1; i <= ans.len; i++) ans.A[i] = (i <= len ? A[i] : 0) + (i <= t.len ? t.A[i] : 0);
		for(int i = 1; i < ans.len; i++) if(ans.A[i] > 9) ans.A[i+1] += ans.A[i] / 10, ans.A[i] %= 10;
		while(ans.A[ans.len] > 9) ans.A[ans.len+1] = ans.A[ans.len] / 10, ans.A[ans.len] %= 10, ans.len++;
		return ans;
	}
	LL operator += (const LL& t) {
		*this = *this + t;
		return *this;
	}
	LL operator + (const int& t) const {
		LL ans; ans.len = max(len, 1);
		for(int i = 1; i <= ans.len; i++) ans.A[i] = A[i]; ans.A[1] += t;
		for(int i = 1; i < ans.len; i++) if(ans.A[i] > 9) ans.A[i+1] += ans.A[i] / 10, ans.A[i] %= 10;
		while(ans.A[ans.len] > 9) ans.A[ans.len+1] = ans.A[ans.len] / 10, ans.A[ans.len] %= 10, ans.len++;
		return ans;
	}
	LL operator += (const int& t) {
		*this = *this + t;
		return *this;
	}
	LL operator ++ () { // ++this;
		*this = *this + 1;
		return *this;
	}
	LL operator ++ (int x) { // this++;
		*this = *this + 1;
		return *this - 1;
	}

	LL operator - (const LL& t) const {
		LL ans; ans.len = max(len, t.len);
		for(int i = 1; i <= ans.len; i++) ans.A[i] = A[i] - t.A[i];
		for(int i = 1; i < ans.len; i++) if(ans.A[i] < 0) {
			int tmp = (-ans.A[i] + 9) / 10;
			ans.A[i+1] -= tmp; ans.A[i] += tmp * 10;
		}
		while(!ans.A[ans.len]) ans.len--;
		return ans;
	}
	LL operator -= (const LL& t) {
		*this = *this - t;
		return *this;
	}
	LL operator - (const int& t) const {
		LL ans; ans.len = len;
		for(int i = 1; i <= ans.len; i++) ans.A[i] = A[i]; ans.A[1] -= t;
		for(int i = 1; i < ans.len; i++) if(ans.A[i] < 0) {
			int tmp = (-ans.A[i] + 9) / 10;
			ans.A[i+1] -= tmp; ans.A[i] += tmp * 10;
		}
		while(!ans.A[ans.len]) ans.len--;
		return ans;
	}
	LL operator -= (const int& t) {
		*this = *this - t;
		return *this;
	}
	LL operator -- () { // --this;
		*this = *this - 1;
		return *this;
	}
	LL operator -- (int x) { // this--;
		*this = *this - 1;
		return *this + 1;
	}

	LL operator * (const LL& t) const {
		LL ans; ans.len = len + t.len - 1;
		if(len < 0 || t.len < 0) return ans.len = -1, ans;
		for(int i = 1; i <= ans.len; i++) ans.A[i] = 0;
		for(int i = 1; i <= len; i++)
			for(int j = 1; j <= t.len; j++) ans.A[i+j-1] += A[i] * t.A[j];
		for(int i = 1; i < ans.len; i++) if(ans.A[i] > 9) ans.A[i+1] += ans.A[i] / 10, ans.A[i] %= 10;
		while(ans.A[ans.len] > 9) ans.A[ans.len+1] = ans.A[ans.len] / 10, ans.A[ans.len] %= 10, ans.len++;
		return ans;
	}
	LL operator *= (const LL& t) {
		*this = *this * t;
		return *this;
	}
	LL operator * (const int& t) const {
		LL ans = t;
		return ans * (*this);
	}
	LL operator *= (const int& t) {
		*this = *this * t;
		return *this;
	}

	bool operator < (const LL& t) const {
		if(len != t.len) return len < t.len;
		for(int i = len; i; i--) if(A[i] != t.A[i]) return A[i] < t.A[i];
		return 0;
	}
	bool operator > (const LL& t) const {
		if(len != t.len) return len > t.len;
		for(int i = len; i; i--) if(A[i] != t.A[i]) return A[i] > t.A[i];
		return 0;
	}
	bool operator == (const LL& t) const {
		if(len != t.len) return 0;
		for(int i = len; i; i--) if(A[i] != t.A[i]) return 0;
		return 1;
	}
	bool operator != (const LL& t) const {
		return !((*this) == t);
	}
	bool operator <= (const LL& t) const {
		return *this < t || *this == t;
	}
	bool operator >= (const LL& t) const {
		return *this > t || *this == t;
	}

	LL operator / (const LL& t) const {
		LL ans, f = 0; ans.len = -1;
		for(int i = 1; i <= len; i++) ans.A[i] = 0;
		for(int i = len; i; i--) {
			f = f * 10 + A[i];
			while(f >= t) {
				f -= t; ans.A[i]++;
				ans.len = max(ans.len, i);
			}
		}
		return ans;
	}
	LL operator /= (const LL& t) {
		*this = *this / t;
		return *this;
	}
	LL operator / (const int& t) const {
		LL ans; int f = 0; ans.len = -1;
		for(int i = 1; i <= len; i++) ans.A[i] = 0;
		for(int i = len; i; i--) {
			f = f * 10 + A[i];
			while(f >= t) {
				f -= t; ans.A[i]++;
				ans.len = max(ans.len, i);
			}
		}
		return ans;
	}
	LL operator /= (const int& t) {
		*this = *this / t;
		return *this;
	}

	void print() {
		if(len < 0){ puts("0"); return ; }
		for(int i = len; i; i--) putchar(A[i] + ‘0‘); putchar(‘\n‘);
		return ;
	}
} A, B;

int main() {
	while(1) {
		A = read(); B = read();
		(A + B).print();
		(A - B).print();
		(A * B).print();
		(A / B).print();
		(A++).print();
		(++A).print();
		(B--).print();
		(--B).print();
	}

	return 0;
}
/*
8997622 2333
*/

再贴这道题的程序。

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cctype>
#include <algorithm>
#include <string>
using namespace std;

int read() {
	int x = 0, f = 1; char c = getchar();
	while(!isdigit(c)){ if(c == ‘-‘) f = -1; c = getchar(); }
	while(isdigit(c)){ x = x * 10 + c - ‘0‘; c = getchar(); }
	return x * f;
}

#define maxn 1010

struct LL {
	int len, A[5010];

	LL() { len = -1; }
	LL(int x) {
		A[1] = x; len = 1;
		if(x) while(A[len] > 9) A[len+1] = A[len] / 10, A[len] %= 10, len++;
		else len = -1;
	}

	LL operator = (const int& t) {
		A[1] = t; len = 1;
		if(t) while(A[len] > 9) A[len+1] = A[len] / 10, A[len] %= 10, len++;
		else len = -1;
		return *this;
	}

	LL operator + (const LL& t) const {
		LL ans; ans.len = max(len, t.len);
		for(int i = 1; i <= ans.len; i++) ans.A[i] = (i <= len ? A[i] : 0) + (i <= t.len ? t.A[i] : 0);
		for(int i = 1; i < ans.len; i++) if(ans.A[i] > 9) ans.A[i+1] += ans.A[i] / 10, ans.A[i] %= 10;
		while(ans.A[ans.len] > 9) ans.A[ans.len+1] = ans.A[ans.len] / 10, ans.A[ans.len] %= 10, ans.len++;
		return ans;
	}
	LL operator += (const LL& t) {
		*this = *this + t;
		return *this;
	}
	LL operator + (const int& t) const {
		LL ans; ans.len = max(len, 1);
		for(int i = 1; i <= ans.len; i++) ans.A[i] = A[i]; ans.A[1] += t;
		for(int i = 1; i < ans.len; i++) if(ans.A[i] > 9) ans.A[i+1] += ans.A[i] / 10, ans.A[i] %= 10;
		while(ans.A[ans.len] > 9) ans.A[ans.len+1] = ans.A[ans.len] / 10, ans.A[ans.len] %= 10, ans.len++;
		return ans;
	}
	LL operator += (const int& t) {
		*this = *this + t;
		return *this;
	}
	LL operator ++ () { // ++this;
		*this = *this + 1;
		return *this;
	}
	LL operator ++ (int x) { // this++;
		*this = *this + 1;
		return *this - 1;
	}

	LL operator - (const LL& t) const {
		LL ans; ans.len = max(len, t.len);
		for(int i = 1; i <= ans.len; i++) ans.A[i] = A[i] - t.A[i];
		for(int i = 1; i < ans.len; i++) if(ans.A[i] < 0) {
			int tmp = (-ans.A[i] + 9) / 10;
			ans.A[i+1] -= tmp; ans.A[i] += tmp * 10;
		}
		while(!ans.A[ans.len]) ans.len--;
		return ans;
	}
	LL operator -= (const LL& t) {
		*this = *this - t;
		return *this;
	}
	LL operator - (const int& t) const {
		LL ans; ans.len = len;
		for(int i = 1; i <= ans.len; i++) ans.A[i] = A[i]; ans.A[1] -= t;
		for(int i = 1; i < ans.len; i++) if(ans.A[i] < 0) {
			int tmp = (-ans.A[i] + 9) / 10;
			ans.A[i+1] -= tmp; ans.A[i] += tmp * 10;
		}
		while(!ans.A[ans.len]) ans.len--;
		return ans;
	}
	LL operator -= (const int& t) {
		*this = *this - t;
		return *this;
	}
	LL operator -- () { // --this;
		*this = *this - 1;
		return *this;
	}
	LL operator -- (int x) { // this--;
		*this = *this - 1;
		return *this + 1;
	}

	LL operator * (const LL& t) const {
		LL ans; ans.len = len + t.len - 1;
		if(len < 0 || t.len < 0) return ans.len = -1, ans;
		for(int i = 1; i <= ans.len; i++) ans.A[i] = 0;
		for(int i = 1; i <= len; i++)
			for(int j = 1; j <= t.len; j++) ans.A[i+j-1] += A[i] * t.A[j];
		for(int i = 1; i < ans.len; i++) if(ans.A[i] > 9) ans.A[i+1] += ans.A[i] / 10, ans.A[i] %= 10;
		while(ans.A[ans.len] > 9) ans.A[ans.len+1] = ans.A[ans.len] / 10, ans.A[ans.len] %= 10, ans.len++;
		return ans;
	}
	LL operator *= (const LL& t) {
		*this = *this * t;
		return *this;
	}
	LL operator * (const int& t) const {
		LL ans = t;
		return ans * (*this);
	}
	LL operator *= (const int& t) {
		*this = *this * t;
		return *this;
	}

	bool operator < (const LL& t) const {
		if(len != t.len) return len < t.len;
		for(int i = len; i; i--) if(A[i] != t.A[i]) return A[i] < t.A[i];
		return 0;
	}
	bool operator > (const LL& t) const {
		if(len != t.len) return len > t.len;
		for(int i = len; i; i--) if(A[i] != t.A[i]) return A[i] > t.A[i];
		return 0;
	}
	bool operator == (const LL& t) const {
		if(len != t.len) return 0;
		for(int i = len; i; i--) if(A[i] != t.A[i]) return 0;
		return 1;
	}
	bool operator != (const LL& t) const {
		return !((*this) == t);
	}
	bool operator <= (const LL& t) const {
		return *this < t || *this == t;
	}
	bool operator >= (const LL& t) const {
		return *this > t || *this == t;
	}

	LL operator / (const LL& t) const {
		LL ans, f = 0; ans.len = -1;
		for(int i = 1; i <= len; i++) ans.A[i] = 0;
		for(int i = len; i; i--) {
			f = f * 10 + A[i];
			while(f >= t) {
				f -= t; ans.A[i]++;
				ans.len = max(ans.len, i);
			}
		}
		return ans;
	}
	LL operator /= (const LL& t) {
		*this = *this / t;
		return *this;
	}
	LL operator / (const int& t) const {
		LL ans; int f = 0; ans.len = -1;
		for(int i = 1; i <= len; i++) ans.A[i] = 0;
		for(int i = len; i; i--) {
			f = f * 10 + A[i];
			while(f >= t) {
				f -= t; ans.A[i]++;
				ans.len = max(ans.len, i);
			}
		}
		return ans;
	}
	LL operator /= (const int& t) {
		*this = *this / t;
		return *this;
	}

	void print() {
		if(len < 0){ putchar(‘0‘); return ; }
		for(int i = len; i; i--) putchar(A[i] + ‘0‘);
		return ;
	}
};

LL f[maxn];
LL C(LL n, int m) {
	LL sum = 1;
	for(LL i = n; i >= n - m + 1; i--) sum *= i;
	for(int i = 1; i <= m; i++) sum /= i;
	return sum;
}
LL dp(int n) {
	LL& ans = f[n];
	if(ans >= 0) return ans;
	if(!n) return ans = 1;
	ans = 0;
//	printf("dp(%d)\n", n);
	for(int s1 = n - 1; s1 >= 0; s1--)
		for(int s2 = s1; s2 >= 0; s2--) {
			int s3 = n - s1 - s2 - 1;
			if(s3 < 0) continue;
			if(s2 < s3) break;
//			printf("%d %d %d\n", s1, s2, s3);
			if(s1 == s3) ans += C(dp(s1) + 2, 3);
			else if(s1 == s2)
				ans += C(dp(s1) + 1, 2) * dp(s3);
			else if(s2 == s3)
				ans += C(dp(s2) + 1, 2) * dp(s1);
			else ans += dp(s1) * dp(s2) * dp(s3);
//			printf("dp(%d): %lld\n", n, ans);
		}
//	printf("%d: %d\n", n, ans);
	return ans;
}

string Names[15] = {"甲", "乙", "丙", "丁", "戊", "己", "庚", "辛", "壬", "癸"};
string getname(int n) {
	if(n <= 10) return Names[n-1] + string("烷");
	char Name[maxn]; memset(Name, 0, sizeof(Name));
	sprintf(Name, "%d烷", n);
	return string(Name);
}

int main() {
	memset(f, -1, sizeof(f));

	while(1) {
		int n = read();
		LL ans = 0, getrid = 0;
		if(n & 1) {
			for(int s1 = (n >> 1); s1 >= 0; s1--)
				for(int s2 = s1; s2 >= 0; s2--)
					for(int s3 = s2; s3 >= 0; s3--) {
						int s4 = n - s1 - s2 - s3 - 1;
						if(s4 < 0) continue;
						if(s3 < s4) break;
//						printf("%d %d %d %d\n", s1, s2, s3, s4);
						LL lstans = ans;
						if(s1 == s4) ans += C(dp(s1) + 3, 4);
						else if(s1 == s3) ans += C(dp(s1) + 2, 3) * dp(s4);
						else if(s2 == s4) ans += C(dp(s2) + 2, 3) * dp(s1);
						else {
							int S[4] = {s1, s2, s3, s4}, l = 0, r = 0;
							LL tmp = 1;
							while(r < 4) {
								while(r < 3 && S[l] == S[r+1]) r++;
								tmp *= C(dp(S[l]) + r - l, r - l + 1);
								l = r = r + 1;
							}
							ans += tmp;
						}
					}
		}
		else {
			for(int s1 = (n >> 1) - 1; s1 >= 0; s1--)
				for(int s2 = s1; s2 >= 0; s2--)
					for(int s3 = s2; s3 >= 0; s3--) {
						int s4 = n - s1 - s2 - s3 - 1;
						if(s4 < 0) continue;
						if(s3 < s4) break;
//						printf("%d %d %d %d\n", s1, s2, s3, s4);
						LL lstans = ans;
						if(s1 == s4) ans += C(dp(s1) + 3, 4);
						else if(s1 == s3) ans += C(dp(s1) + 2, 3) * dp(s4);
						else if(s2 == s4) ans += C(dp(s2) + 2, 3) * dp(s1);
						else {
							int S[4] = {s1, s2, s3, s4}, l = 0, r = 0;
							LL tmp = 1;
							while(r < 4) {
								while(r < 3 && S[l] == S[r+1]) r++;
								tmp *= C(dp(S[l]) + r - l, r - l + 1);
								l = r = r + 1;
							}
							ans += tmp;
						}
					}
			ans += C(dp(n >> 1) + 1, 2);
		}
		cout << getname(n); printf("有 "); ans.print(); puts(" 种同分异构体");
	}

	return 0;
}
时间: 2024-12-10 02:41:15

复(学)习化学时突然的一个 idea的相关文章

H?t?m?l?5? ?学?习?:?H?T?M?L?5?新?增?结?构?标?签

引言 在本节中,笔者将向大家讲述三部分内容,分别介绍HTML5时代的召唤,跟HTML4的区别,以及HTML5中带来的新的结构标签. HTML5时代的召唤 HTML4与HTML5的区别 HTML5新结构标签 HTML5时代的召唤 上一代的HTML的标准: HTML 4.01 和 XHTML 1.0 距离今天已经发布了10多年了,而Web端的应用也已经翻天覆地的变换.而且Web前端没有一个统一的通用的互联网标准,各个浏览器间拥有太多的不兼容,在维护这些浏览器兼容性浪费了太多的时间.再有就是之前的多媒

C#winform两个或多个panel重叠布局时如何显示一个

现象:panel1和panel2或更多panel,叠放在一起,panel和panel2是同一层次的.panel1和panel2切换时只能显示一个panel,如何切换呢? 解决方法: 1.打开vs视图-其他窗口-文档大纲,看看层次关系,就可以看出最上面的panel是窗体里显示出来的.如何让panel2出现在窗体去编辑呢? 2.拖动panel2到panel1前面,即可编辑panel2

今天和组内一起写代码时碰到了一个关于命名冲突的问题,最后用js命名空间的方法解决的。

//第一步,首先创建一个全局变量,可以放在自己的js方法库中方便以后用,这个就是用来注册命名空间的方法. ns = function(namespace){ var arr = namespace.split('.');  //将传入的字符串如"com.test.lzn"以'.'隔开做成一个数组 var strNamespace = ""; //这个是为了保存每一步循环进去的包名 for(var i=0;i<arr.length;i++) { if(i!=0)

删除数据时弹出一个确认对话框

使用js实现点击按钮删除数据时弹出一个确认是否删除的对话框: <input type="button" class="wz2 btn" value="删除" onClick="sc('{$vo.name}','__URL__/delete?aid={$vo.id}')"/> <script type="text/javascript"> function sc($name,$ulr)

如何在tomcat启动时加载一个类

Tomcat启动时classloader加载顺序 Tomcat的class加载的优先顺序一览   1.最先是$JAVA_HOME/jre/lib/ext/下的jar文件.   2.环境变量CLASSPATH中的jar和class文件.   3.$CATALINA_HOME/common/classes下的class文件.   4.$CATALINA_HOME/commons/endorsed下的jar文件.   5.$CATALINA_HOME/commons/i18n下的jar文件.   6.

C/C++,Java,PHP,JavaScript,Json数组、对象赋值时,最后一个元素后面是否可以带逗号?

1 C,C++,Java,PHP都能容忍末尾的逗号 C,C++,Java中对数组赋值时,最后一个元素末尾的逗号可有可无.下面两行代码对这些语言来说是等效的. int a[] = {1,2,3}; /* 正确 */ int a[] = {1,2,3,}; /* 正确 */ PHP这一点也继承了C的特点,下面的两行代码等效. $a = array(1,2,3); /* 正确 */ $a = array(1,2,3,); /* 正确 */ 2 JavaScript视末尾逗号为语法错误! 然而到了Jav

ios 仿新浪微博 UINavigationController 向左滑动时显示上一个控制器的View.

仿新浪微博 UINavigationController 向左滑动时显示上一个控制器的View. 实现原理,UINavigationController 的 self.view显示时把当前显示的view截图下来,保存到一个数组中.当push一个view时把上一个view的截图放到self.view后面,当self.view向右拖动时显示上一个view. NavigationController.m #import "NavigationController.h" @interface

WinCE C#程序,控制启动时只能启动一个程序,使用互斥量来实现,该实现方法测试通过

</pre><pre code_snippet_id="430174" snippet_file_name="blog_20140718_5_4634982" name="code" class="csharp"> </pre><pre code_snippet_id="430174" snippet_file_name="blog_20140718_5_

创业初期如何做公关,学老罗去讲好一个故事

(文丨舍予兄)前段时间老罗的发布会又一次刷爆了朋友圈,似乎主流媒体都非常乐于看到一个个性狂狷的人开始慢慢收敛,尽管过程中老罗多多少少表现出 不情愿,但大部分人都看的出来,胖子累了.老罗的手机我当然不敢置评,参考王自如,毕竟小命要紧:但是老罗公关方面的可观赏程度还是不错的.所以这篇文 章,不吹不黑,只是单纯地从公关的角度分析,创业者如何像老罗一样,讲好一个引人共鸣的故事. 对于早期创始人来说,公关行为的最高目标就是让用户产生“共鸣”,马云和李彦宏,草根逆袭和技术精英的故事,哪个更吸引人?所以作为一