Codeforces 902D/901B

传送门:http://codeforces.com/contest/902/problem/D

本题是一个数学问题——多项式整除。

对于两个整数ab,求最大公约数gcd(a,b)的辗转相除法的函数如下:

int gcd(int a, int b) {
    if (b == 0) return a;
    return gcd(b, a % b);
}

一次辗转相除法将数对(a,b)转化成(b,a mod b),直至b=0。

对于多项式A(x),定义deg A(x)为多项式的次数。对于多项式AB,定义多项式mod运算:若A(x)=B(xD(x)+R(x),deg R(x)<deg B(x),则R(x)A(x) mod B(x)。

于是,一次辗转相除将多项式对(A,B)转化成(B,A mod B),直至B=0。

已知两个多项式A(x)、B(x)的系数在{-1,0,1}中取值,且deg A(x)deg B(x);构成的多项式对(A,B),经过n次辗转相除后结束操作。求可能的多项式A(x)、B(x)。

考虑整数的情形:Fibonacci数列:F(0)=1,F(1)=1,F(n+1)=F(n)+F(n-1)。

于是,一次辗转相除法将(F(n+1),F(n))转化成(F(n),F(n-1))。于是,(F(n),F(n-1))在n次辗转相除后结束操作。

类似地,构造多项式的情形:P(0)=1,P(1)=xP(n+1)=x·P(n)±P(n-1)。

递推时,维护P(n+1)的系数在{-1,0,1}中取值,这可以通过符号选择(+/-)实现。

还可以构造多项式:P(0)=1,P(1)=xP(n+1)x·P(n)+P(n-1) mod2。

参考程序如下:

#include <stdio.h>
#define MAX_N 200

int p[MAX_N][MAX_N];

int main(void)
{
    int n;
    scanf("%d", &n);
    p[0][0] = 1;
    p[1][1] = 1;
    for (int i = 1; i < n; i++) {
        //p[i + 1] = {x * p[i] + p[i - 1]} % 2;
        for (int j = 0; j <= i; j++)
            p[i + 1][j + 1] += p[i][j];
        for (int j = 0; j <= i - 1; j++)
            p[i + 1][j] += p[i - 1][j];
        for (int j = 0; j <= i + 1; j++)
            p[i + 1][j] %= 2;
    }
    int deg;
    for (deg = n; p[n][deg] == 0; deg--);
    printf("%d
", deg);
    for (int i = 0; i <= deg; i++)
        printf("%d ", p[n][i]);
    printf("
");
    for (deg = n - 1; p[n - 1][deg] == 0; deg--);
    printf("%d
", deg);
    for (int i = 0; i <= deg; i++)
        printf("%d ", p[n - 1][i]);
    printf("
");
    return 0;
}
原文地址:https://www.cnblogs.com/siuginhung/p/8076457.html