首先考虑一个问题,设
u∗A(i)+v∗A(i+1)=x∗A(i/2)+y∗A(i/2+1)
,
i,u,v
为已知量,
x,y
为未知量,求在
i
分别为奇数和偶数时
i
为偶数时,
i
为奇数时,
所以得出:
i
为偶数时,
回到原问题。由于
N<=10100
的数据范围,一步一步地递推肯定是行不通的。我们就考虑一倍一倍地递推。
首先不断地把
N
除以
然后可以看出,结果
=1∗A(N/2)+1∗A(N/2+1)
。此时,根据前面得出的结论,不断地把
N
缩小一倍,最后可以得到
代码:
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 105;
struct cyx {
int n, a[N];
cyx() {}
cyx(int _n) :
n(_n) {memset(a, 0, sizeof(a));}
};
cyx read() {
int i = 1, j; cyx res = cyx(0); char c; bool flag = 0;
while ((c = getchar()) < '0' || c > '9');
if (c - 48) res.a[res.n = 1] = c - 48, flag = 1;
while ((c = getchar()) >= '0' && c <= '9') {
if (c - 48) flag = 1;
if (flag) res.a[++res.n] = c - 48;
}
if (!res.n) res.a[res.n = 1] = 0;
for (j = res.n; i < j; i++, j--) swap(res.a[i], res.a[j]);
return res;
}
void write(cyx num) {
int i; for (i = num.n; i; i--)
printf("%d", num.a[i]);
printf("\n");
}
cyx div2(cyx num) {
int i; for (i = num.n; i; i--) {
if (num.a[i] & 1) num.a[i - 1] += 10;
num.a[i] >>= 1;
}
while (num.n > 1 && !num.a[num.n]) num.n--;
return num;
}
cyx plus1(cyx num) {
int i = 1; while (num.a[i] == 9) num.a[i] = 0, i++;
num.a[i]++; if (num.a[num.n + 1]) num.n++; return num;
}
cyx add(cyx a, cyx b) {
cyx res = cyx(max(a.n, b.n)); int i;
for (i = 1; i <= res.n; i++) {
res.a[i] += a.a[i] + b.a[i];
if (res.a[i] > 9) res.a[i] -= 10, res.a[i + 1]++;
}
if (res.a[res.n + 1]) res.n++; return res;
}
cyx solve(cyx num) {
if (num.n == 1 && (num.a[1] == 0 || num.a[1] == 1)) return num;
while (!(num.a[1] & 1)) num = div2(num);
cyx l = div2(num), r = plus1(l), u = cyx(1), v = cyx(1);
u.a[1] = v.a[1] = 1; while (l.n > 1 || l.a[1]) {
if (l.a[1] & 1) v = add(u, v); else u = add(u, v);
l = div2(l); r = plus1(l);
}
return v;
}
int main() {
int T; scanf("%d", &T);
while (T--) write(solve(read()));
return 0;
}