1779. Fibonacci Sequence Multiplication
Constraints
Time Limit: 1 secs, Memory Limit: 63.9990234375 MB
Description
Maybe all of you are familiar with Fibonacci sequence. Now you are asked to solve a special version of Fibonacci sequence: The Multiplication Version.
The Fibonacci sequence – Multiplication version is defined as followed:
- F[1] = a
- F[2] = b
- F[i] = F[i-1] × F[i-2] ( for all i > 2)
Now given a, b and n, I’d like you to calculate F[n].
In case of large output, if the number of digits of F[n] is larger than 1000, you just need to output “Ooops!” instead of F[n]. So, it’s a “Limited Edition”.
Input
There are multiple test cases.
The first line is an integer T(1 ≤ T ≤ 50) indicating the number of test cases.
For each case, there are three integers a, b and n (1 ≤ a, b, n ≤ 109) in a line.
Output
Output F[n] in a line for each test case. If the number of digits of F[n] is larger than 1000, just output “Ooops!” instead of F[n].
Sample Input
5 1 2 1 1 2 2 1 2 4 3 2 10 13 14 520
Sample Output
1 2 4 179707499645975396352 Ooops!
这是我第一次写的代码,高精度(基数为10,也就是十进制),用时0.04s:
当n达到20的时候,除非1 1 20的情况,否则必然Ooops
#include <stdio.h>
#include <string.h>
int a1[3010], a2[3010], a3[3010];
char f1[11], f2[11];
void ready() {//转化成数组
int temp, i;
memset(a1, 0, sizeof(a1));
memset(a2, 0, sizeof(a2));
memset(a3, 0, sizeof(a3));
for (temp = (int)strlen(f1), i = 0; i < temp; i++) {
a1[i] = f1[temp - 1 - i] - '0';
}
for (temp = (int)strlen(f2), i = 0; i < temp; i++) {
a2[i] = f2[temp - 1 - i] - '0';
}
}
void multi() {
int length_a1, length_a2, max_length_a3, i, j;
for (length_a1 = 3009; length_a1 > 0 && a1[length_a1] == 0; length_a1--);//判断两个乘数的长度
for (length_a2 = 3009; length_a2 > 0 && a2[length_a2] == 0; length_a2--);
length_a1++;
length_a2++;
max_length_a3 = length_a1 + length_a2;
memset(a3, 0, sizeof(a3));
for (i = 0; i <= length_a1; i++) {//高精度乘法
for (j = 0; j <= length_a2; j++) {
a3[i + j] += a1[i] * a2[j];
a3[i + j + 1] += a3[i + j] / 10;
a3[i + j] %= 10;
}
}
memset(a1, 0, sizeof(a1));
for (i = 0; i <= length_a2; i++) {
a1[i] = a2[i];
}
memset(a2, 0, sizeof(a2));
for (i = 0; i <= max_length_a3; i++) {
a2[i] = a3[i];
}
}
int check_length_a2() {//判断当前长度
int i;
for (i = 3009; i > 0 && a2[i] == 0; i--);
return i + 1;
}
int main() {
int t, temp, n, i;
scanf("%d", &t);
while (t--) {
memset(f1, '\0', sizeof(f1));
memset(f2, '\0', sizeof(f2));
scanf("%s %s %d", f1, f2, &n);
ready();
if (n == 1) {//各种预先判断
printf("%s\n", f1);
continue;
}
if (n == 2) {
printf("%s\n", f2);
continue;
}
if (f1[0] == '1' && f1[1] == '\0' && f2[0] == '1' && f2[1] == '\0') {
printf("1\n");
continue;
}
if (n >= 20) {//当n达到20就会爆
printf("Ooops!\n");
continue;
}
n = n - 2;
while (check_length_a2() <= 1000 && n--) {
multi();
}
temp = check_length_a2();
if (temp <= 1000) {
for (i = temp - 1; i >= 0; i--) {
printf("%d", a2[i]);
}
printf("\n");
} else {
printf("Ooops!\n");
}
}
return 0;
}
试试大基数,用了0s,注意这种做法有好多陷阱:
#include <stdio.h>
#include <string.h>
#include <math.h>
int base_index = 9;//基数为10的9次方
long long unit_base = (long long)pow(10, 9);//基数大小
long long unit[2500];//基数为10^9的最大长度数组
long long per_base[] = {1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000};//构建unit数组用到的
long long a1[2500], a2[2500], a3[2500];
int length_a1, length_a2, length_f1, length_f2, ans_length;
char f1[11], f2[11];
int get_length(int length_f) {
return length_f % 9 == 0 ? length_f / 9 : length_f / 9 + 1;
}
void ready() {//转化数组
int i, j, k;
memset(a1, 0, sizeof(a1));
memset(a2, 0, sizeof(a2));
memset(a3, 0, sizeof(a3));
length_a1 = get_length((int)strlen(f1));
length_a2 = get_length((int)strlen(f2));
for (i = 0, j = (int)strlen(f1) - 1; i < length_a1; i++) {//转化为基数为10^9的进制数
for (k = 0; k < 9 && j >= 0; k++) {
a1[i] += per_base[k] * (f1[j--] - '0');
}
}
for (i = 0, j = (int)strlen(f2) - 1; i < length_a2; i++) {
for (k = 0; k < 9 && j >= 0; k++) {
a2[i] += per_base[k] * (f2[j--] - '0');
}
}
}
void multi() {
int max_length_a3, i, j;
for (length_a1 = 2500 - 1; length_a1 > 0 && a1[length_a1] == 0; length_a1--);//判断两个乘数的长度
for (length_a2 = 2500 - 1; length_a2 > 0 && a2[length_a2] == 0; length_a2--);
length_a1++;
length_a2++;
max_length_a3 = length_a1 + length_a2;
memset(a3, 0, sizeof(a3));
for (i = 0; i <= length_a1; i++) {//高精度乘法
for (j = 0; j <= length_a2; j++) {
a3[i + j] += a1[i] * a2[j];
a3[i + j + 1] += a3[i + j] / unit_base;
a3[i + j] %= unit_base;
}
}
memset(a1, 0, sizeof(a1));//数组转移,准备下一次的比较
for (i = 0; i <= length_a2; i++) {
a1[i] = a2[i];
}
memset(a2, 0, sizeof(a2));
for (i = 0; i <= max_length_a3; i++) {
a2[i] = a3[i];
}
}
int check_length_a2() {//判断当前长度
int i, k;
for (i = 2500 - 1; i > 0 && a2[i] == 0; i--);
for (k = 8; k >= 0; k--) {
if (a2[i] >= per_base[k]) {
break;
}
}
ans_length = i + 1;
return i * 9 + k + 1;
}
void print(int i) {//注意这里!!!!wa了我好久,必须把每一个除了最大位的数的前导零输出
int k;
if (a2[i] == 0) {//当等于0的时候特殊处理
printf("000000000");
return;
}
for (k = 8; k >= 0 && a2[i] != 0; k--) {
if (a2[i] >= per_base[k]) {
break;
}
}
k = 8 - k;
while (k--) {//输出前导零
printf("0");
}
printf("%lld", a2[i]);
}
int main() {
int t, temp, n, i;
scanf("%d", &t);
while (t--) {
memset(f1, '\0', sizeof(f1));
memset(f2, '\0', sizeof(f2));
scanf("%s %s %d", f1, f2, &n);
if (n == 1) {//各种预先判断
printf("%s\n", f1);
continue;
}
if (n == 2) {
printf("%s\n", f2);
continue;
}
if (f1[0] == '1' && f1[1] == '\0' && f2[0] == '1' && f2[1] == '\0') {
printf("1\n");
continue;
}
if (n >= 20) {//当n达到20就会爆
printf("Ooops!\n");
continue;
}
ready();
n = n - 2;
while (1) {
temp = check_length_a2();
if (!(temp <= 1000 && n--))
break;
multi();
}
if (temp <= 1000) {
for (i = ans_length - 1; i >= 0; i--) {
if (i != ans_length - 1) {
print(i);
} else {
printf("%lld", a2[i]);
}
}
printf("\n");
} else {
printf("Ooops!\n");
}
}
return 0;
}