传送门:http://codeforces.com/contest/902/problem/D
本题是一个数学问题——多项式整除。
对于两个整数a、b,求最大公约数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)为多项式的次数。对于多项式A、B,定义多项式mod运算:若A(x)=B(x)·D(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)=x,P(n+1)=x·P(n)±P(n-1)。
递推时,维护P(n+1)的系数在{-1,0,1}中取值,这可以通过符号选择(+/-)实现。
还可以构造多项式:P(0)=1,P(1)=x,P(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; }