【BZOJ1089】[SCOI2003]严格n元树【递推】【高精度】
2016-03-04 20:56
555 查看
以为可以组合数分类递推求和,然而还是too naive。
设f[i]为高度小于等于i的树的方案数,那么有f[i] = (f[i - 1] ^ n) + 1。
答案为f[d] - f[d - 1]
然后敲个高精度就好啦。
话说最大数据似乎根本跑不了。
/* Footprints In The Blood Soaked Snow */
#include <cstdio>
#include <algorithm>
using namespace std;
const int maxn = 10005;
struct bigint {
int num[maxn], len;
bigint() {
for(int i = 0; i < maxn; i++) num[i] = 0;
len = 1;
}
void read(int x) {
for(len = 0; x; x /= 10) num[len++] = x % 10;
}
bigint operator + (const bigint &a) {
bigint c; c.len = max(len, a.len) + 1;
for(int i = 0; i < c.len; i++) {
c.num[i] += num[i] + a.num[i];
c.num[i + 1] += c.num[i] / 10;
c.num[i] %= 10;
}
for(; c.len > 1 && !c.num[c.len - 1]; c.len--);
return c;
}
bigint operator - (const bigint &a) {
bigint c; c.len = max(len, a.len);
for(int i = 0; i < c.len; i++) {
c.num[i] += num[i] - a.num[i];
if(c.num[i] < 0) {
c.num[i] += 10;
c.num[i + 1] -= 1;
}
}
for(; c.len > 1 && !c.num[c.len - 1]; c.len--);
return c;
}
bigint operator * (const bigint &a) {
bigint c; c.len = len + a.len + 1;
for(int i = 0; i < len; i++) for(int j = 0; j < a.len; j++)
c.num[i + j] += num[i] * a.num[j];
for(int i = 0; i < c.len; i++) {
c.num[i + 1] += c.num[i] / 10;
c.num[i] %= 10;
}
for(; c.len > 1 && !c.num[c.len - 1]; c.len--);
return c;
}
bigint operator ^ (int n) {
bigint ans; ans.read(1);
for(bigint t = *this; n; n >>= 1, t = t * t) if(n & 1) ans = ans * t;
for(; ans.len > 1 && !ans.num[ans.len - 1]; ans.len--);
return ans;
}
void print() {
for(int i = len - 1; i >= 0; i--) printf("%d", num[i]);
}
} f2, f1, E;
int main() {
int n, d; scanf("%d%d", &n, &d);
E.read(1); f1 = E;
for(int i = 1; i <= d; i++)
if(i & 1) f2 = (f1 ^ n) + E;
else f1 = (f2 ^ n) + E;
if(~d & 1) swap(f1, f2);
f2 = f2 - f1;
f2.print();
return 0;
}
设f[i]为高度小于等于i的树的方案数,那么有f[i] = (f[i - 1] ^ n) + 1。
答案为f[d] - f[d - 1]
然后敲个高精度就好啦。
话说最大数据似乎根本跑不了。
/* Footprints In The Blood Soaked Snow */
#include <cstdio>
#include <algorithm>
using namespace std;
const int maxn = 10005;
struct bigint {
int num[maxn], len;
bigint() {
for(int i = 0; i < maxn; i++) num[i] = 0;
len = 1;
}
void read(int x) {
for(len = 0; x; x /= 10) num[len++] = x % 10;
}
bigint operator + (const bigint &a) {
bigint c; c.len = max(len, a.len) + 1;
for(int i = 0; i < c.len; i++) {
c.num[i] += num[i] + a.num[i];
c.num[i + 1] += c.num[i] / 10;
c.num[i] %= 10;
}
for(; c.len > 1 && !c.num[c.len - 1]; c.len--);
return c;
}
bigint operator - (const bigint &a) {
bigint c; c.len = max(len, a.len);
for(int i = 0; i < c.len; i++) {
c.num[i] += num[i] - a.num[i];
if(c.num[i] < 0) {
c.num[i] += 10;
c.num[i + 1] -= 1;
}
}
for(; c.len > 1 && !c.num[c.len - 1]; c.len--);
return c;
}
bigint operator * (const bigint &a) {
bigint c; c.len = len + a.len + 1;
for(int i = 0; i < len; i++) for(int j = 0; j < a.len; j++)
c.num[i + j] += num[i] * a.num[j];
for(int i = 0; i < c.len; i++) {
c.num[i + 1] += c.num[i] / 10;
c.num[i] %= 10;
}
for(; c.len > 1 && !c.num[c.len - 1]; c.len--);
return c;
}
bigint operator ^ (int n) {
bigint ans; ans.read(1);
for(bigint t = *this; n; n >>= 1, t = t * t) if(n & 1) ans = ans * t;
for(; ans.len > 1 && !ans.num[ans.len - 1]; ans.len--);
return ans;
}
void print() {
for(int i = len - 1; i >= 0; i--) printf("%d", num[i]);
}
} f2, f1, E;
int main() {
int n, d; scanf("%d%d", &n, &d);
E.read(1); f1 = E;
for(int i = 1; i <= d; i++)
if(i & 1) f2 = (f1 ^ n) + E;
else f1 = (f2 ^ n) + E;
if(~d & 1) swap(f1, f2);
f2 = f2 - f1;
f2.print();
return 0;
}
相关文章推荐
- HDU1568(Fobonacci公式)
- VIJOS P1040 高精度乘法
- 1874. Three little pigs
- 计算圆点坐标
- 如何通过excel公式查找一列数据中的相同项目?
- 费马小定理
- 偶数之和
- Sicily 1166 Computer Transformat
- 阶乘——高精度求法
- [BZOJ1089][SCOI2003][递推][高精度]严格n元树
- HDU1063 Exponentiation
- 整数对
- lab104_2
- POJ1001大数相乘
- POJ1503大数相加
- java 读excel包括不同版本读取,读合并单元格和读公式
- 高精度计算bign类
- 424 Integer Inquiry题解
- 贝叶斯定理学习
- 高精度4位压缩法原理与实现