1. 程式人生 > >2017 ICPC 南寧 ,Twice Equation (線性遞推 + 大數)

2017 ICPC 南寧 ,Twice Equation (線性遞推 + 大數)

Twice Equation

For given L, find the smallest n no smaller than L for which there exists an positive integer m for which 2m(m + 1) = n(n + 1).

Input

This problem contains multiple test cases. The first line of a multiple input is an integer T (1 ≤ T < 1000) followed by T input lines. Each line contains an integer L (1 ≤ L < 10190).

Output

For each given L, output the smallest n. If available n does not exist, output ‘−1’.

Sample Input

3

1

4

21

Sample Output

3

20

119

題意:給定一個L,求一個最小數 n , 使 n >= L , 且滿足方程 2*m*(m + 1) = n*(n + 1) 有解

思路:暴力打表出前面幾項,為 3, 20, 119, 696, 4059, 23660, 137903,  顯然肯定是找規律,也就是求線性遞推式係數,最後得F[n] = 7 * F[n - 1] - 7 * F[n - 2] + F[n - 3] .

C++ AC: 為什麼不是 java 大數,因為不會 

#include<bits/stdc++.h>
#define debug(x) cout << "[" << #x <<": " << (x) <<"]"<< endl
#define pii pair<int,int>
#define clr(a,b) memset((a),b,sizeof(a))
#define rep(i,a,b) for(int i = a;i < b;i ++)
#define pb push_back
#define MP make_pair
#define LL long long
#define INT(t) int t; scanf("%d",&t)
#define LLI(t) LL t; scanf("%I64d",&t)

using namespace std;

char ans[1000][210];
char tmp[210];                  /// jian
char tmp1[210];                 /// cheng
char tmp2[210];                 /// add
char seven[10] = {'7', '\0'};

void bigadd(char *s,char *t){
    int lens = strlen(s),lent = strlen(t);
    int xx[210] = {0};
    int p = 0;
    while(lens > 0 && lent > 0) xx[p ++] = s[-- lens] - '0' + t[-- lent] - '0';
    while(lens > 0) xx[p ++] = s[-- lens] - '0';
    while(lent > 0) xx[p ++] = t[-- lent] - '0';

    for(int i = 0;i < p;i ++)
        if(xx[i] >= 10){
            xx[i] -= 10;
            xx[i + 1] ++;
        }

    int pt = 0;
    if(xx[p] != 0) tmp2[pt ++] = xx[p] + '0';
    while(p > 0) tmp2[pt ++] = xx[-- p] + '0';
    tmp2[pt] = '\0';
}

void bigjian(char *a, char *b) {
    int i = strlen(a) - 1, j = strlen(b) - 1;
    int x = 0, c[205] = {0}, flag = 1, d[205] = {0}, f[205] = {0};
    for(int l = 0; l <= i; l++)
        c[l] = a[l] - '0';
    for(int l = 0; l <= j; l++)
        d[l] = b[l] - '0';
    while(j != -1) {
        if(c[i] < d[j]) {
            c[i] += 10;
            c[i - 1] -= 1;
        }
        f[x++] = c[i] - d[j];
        i--;
        j--;
    }
    while(i >= 0) {
        if(c[i] < 0) {
            c[i] += 10;
            c[i - 1] -= 1;
        }
        f[x++] = c[i];
        i--;
    }
    int p = 0;
    if(f[x - 1] == 0)
        flag = 0;
    for(int y = x - 1; y >= 0; y--) {
        if(f[y] != 0)
            flag = 1;
        if(flag == 1)
            tmp[p ++] = f[y] + '0';
    }
    if(flag == 0)
        tmp[p ++] = '0';
    tmp[p] = '\0';
}

void bigx(char *a, char *b) {
    int x, k, lena, lenb, lenb1, c[210] = {0};
    lena = strlen(a) - 1;
    lenb = strlen(b);
    lenb1 = lenb;
    while(lenb--) {
        x = lenb1 - lenb - 1;
        for(int i = lena; i >= 0; i--) {
            k = (a[i] - '0') * (b[lenb] - '0');
            c[x] += k;
            if(c[x] >= 10) {
                c[x + 1] += c[x] / 10;
                c[x] %= 10;
            }
            x++;
        }
    }
    int p = 0;
    if(c[x] != 0)
        tmp1[p ++] = c[x] + '0';
    for(int i = x - 1; i >= 0; i--)
        tmp1[p ++] = c[i] + '0';
    tmp1[p] = '\0';
}

int main()
{
    ans[0][0] = '3'; ans[0][1] = '\0';
    ans[1][0] = '2'; ans[1][1] = '0'; ans[1][2] = '\0';
    ans[2][0] = '1'; ans[2][1] = '1'; ans[2][2] = '9'; ans[2][3] = '\0';
    int i;
    for(i = 3;;i ++){
        char fff[210] = {0};
        bigx(ans[i - 1],seven);
        strcpy(fff,tmp1);
        char ggg[210] = {0};
        bigx(ans[i - 2],seven);

        strcpy(ggg,tmp1);
        bigjian(fff,ggg);

        strcpy(fff,tmp);
        bigadd(fff,ans[i - 3]);

        if(strlen(tmp2) > 192) break;
        strcpy(ans[i],tmp2);
    }
    int T;
    scanf("%d",&T);
    while(T --){
        char n[210]; scanf("%s",n);
        int len = strlen(n);
        for(int j = 0;j <= i + 1;j ++){
            if(strlen(ans[j]) > len){
                printf("%s\n",ans[j]);
                break;
            }
            else if(strlen(ans[j]) == len){
                if(strcmp(n,ans[j]) <= 0){
                    printf("%s\n",ans[j]);
                    break;
                }
            }
        }
    }
    return 0;
}