复(学)习化学时突然的一个 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的主要内容,如果未能解决你的问题,请参考以下文章