Complete the sequence! (POJ-1398)(差分法)

You probably know those quizzes in Sunday magazines: given the sequence 1, 2, 3, 4, 5, what is the next number? Sometimes it is very easy to answer, sometimes it could be pretty hard. Because these "sequence problems" are very popular, ACM wants to implement them into the "Free Time" section of their new WAP portal.

ACM programmers have noticed that some of the quizzes can be solved by describing the sequence by polynomials. For example, the sequence 1, 2, 3, 4, 5 can be easily understood as a trivial polynomial. The next number is 6. But even more complex sequences, like 1, 2, 4, 7, 11, can be described by a polynomial. In this case, 1/2.n2-1/2.n+1 can be used. Note that even if the members of the sequence are integers, polynomial coefficients may be any real numbers.

Polynomial is an expression in the following form:

P(n) = a D.n D+a D-1.n D-1+...+a 1.n+a 0

. If a D <> 0, the number D is called a degree of the polynomial. Note that constant function P(n) = C can be considered as polynomial of degree 0, and the zero function P(n) = 0 is usually defined to have degree -1.

Input

There is a single positive integer T on the first line of input. It stands for the number of test cases to follow. Each test case consists of two lines. First line of each test case contains two integer numbers S and C separated by a single space, 1 <= S < 100, 1 <= C < 100, (S+C) <= 100. The first number, S, stands for the length of the given sequence, the second number, C is the amount of numbers you are to find to complete the sequence.

The second line of each test case contains S integer numbers X1, X2, ... XS separated by a space. These numbers form the given sequence. The sequence can always be described by a polynomial P(n) such that for every i, Xi = P(i). Among these polynomials, we can find the polynomial Pmin with the lowest possible degree. This polynomial should be used for completing the sequence.
 

Output

For every test case, your program must print a single line containing C integer numbers, separated by a space. These numbers are the values completing the sequence according to the polynomial of the lowest possible degree. In other words, you are to print values P min(S+1), P min(S+2), .... P min(S+C).

It is guaranteed that the results P min(S+i) will be non-negative and will fit into the standard integer type.
 

Sample Input

4
6 3
1 2 3 4 5 6
8 2
1 2 4 7 11 16 22 29
10 2
1 1 1 1 1 1 1 1 1 2
1 10
3

Sample Output

7 8 9
37 46
11 56
3 3 3 3 3 3 3 3 3 3

題意:給定一個長度爲s的數列a1,a2,a3,……,as,並知道它的通項可以用多項式P(n)表示出來,求數列的後c項。

思路:這道題的話,我們可以用差分法來做。下面借鑑一下大佬的思路:

比如說,對於1 2 4 7 11 16 22 29這個數列,我們對於每一項做其和前一項的差,也就是2-1=1, 4-2=2, 7-4=3, ....這樣,我們得到一個1階差分:1, 2, 3, 4, 5, 6, 7。我們再求得2階差分是:1, 1, 1, 1, 1, 1。這時,規律已經有些明顯了。 也就是說,對於任意一個存在合理多項式通項的數列,用差分的方法是可以得到它的解的:只要求得這個n項數列的n-1階差分,然後倒推回去就可以了。 那麼爲什麼可以這樣呢?可以這樣理解:對於任意滿足多項式P(n) = aD.n^D+aD-1.n^D-1+...+a1.n+a0的D階多項式,取一階差分得:tmp = P(n) - P(n - 1)肯定是個D-1階多項式,以此類推,取n-1階差分,就只剩下一個數d (程序中爲f[n-1][0]), 如果d = 0,如果想使得P(n)的階最小,第n-1階差分中接下來的m個數應該都爲0,如果d != 0,當接着的m個數都爲d時,則第n-2階爲1階多項式(只有一階多項式(a1.n + a0, 公差爲a1)的差分才爲一個常數),第n-1階爲0階多項式,才能保證階D最小。

關於差分法:https://baike.baidu.com/item/%E5%B7%AE%E5%88%86%E6%B3%95/2369622?fr=aladdin

https://blog.csdn.net/qq_41679006/article/details/80975436 

AC代碼:

#include <stdio.h>
#include <string>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <math.h>
#include <queue>
#include <stack>
#include <map>
#include <set>
typedef long long ll;
const int maxx=110;
const int mod=10007;
const int inf=0x3f3f3f3f;
const double eps=1e-5;
using namespace std;
int a[maxx][maxx];
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        memset(a,0,sizeof(a));
        int s,c;
        scanf("%d%d",&s,&c);
        for(int i=0; i<s; i++)
            scanf("%d",&a[0][i]);
        for(int i=1; i<s; i++)
            for(int j=0; j<s-i; j++)
                a[i][j]=a[i-1][j+1]-a[i-1][j];
        for (int i=1; i<=c; i ++)
            a[s-1][i]=a[s-1][0];
        for(int i=s-2; i>=0; i--)
            for(int j=0; j<c; j++)
                a[i][s-i+j]=a[i+1][s-i+j-1]+a[i][s-i+j-1];
        for(int i=0; i<c-1; i ++)
            printf("%d ", a[0][s+i]);
        printf("%d\n",a[0][s+c-1]);
    }
    return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章