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

Posted xjr_01

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了复(学)习化学时突然的一个 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;
}

 

以上是关于复(学)习化学时突然的一个 idea的主要内容,如果未能解决你的问题,请参考以下文章

为什么越学反而越蠢?碎片化学习是个骗局

为什么越学反而越蠢?碎片化学习是个骗局

Android插件化学习之路之使用插件中的R资源

北航2022计软期末C++复(预)习

整日碎片化学习“凡不凡”?来看看优秀的Python全栈工程师都是如何学习的

jenkins pipeline之流水线脚本版本化学习二(简化版)