2017 ICPC 南寧 ,Twice Equation (線性遞推 + 大數)
阿新 • • 發佈:2018-12-11
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; }