Codeforces 902 D.GCD of Polynomials 数学,搜索答案

来源:互联网 发布:windows开发unity ios 编辑:程序博客网 时间:2024/04/30 06:23

题意

给出n(1–150).
输出两个多项式A,B从常数到最高次的系数,使得对两个多项式求gcd时,恰好经过n步得到结果.
多项式的gcd一步是指(A(x),B(x))变成(B,A mod B)的过程,且当A mod B为0时,视为得到结果B.
A mod B为多项式求余,参见 long division.
要求两个多项式的所有系数都是1,0,-1.前导系数(最高次项系数)为1,度数(最高次)不超过n,第一个多项式的度数大于第二个.

样例输入
1
样例输出
1
0 1
0
1
表示x和1,进行一次得到结果.(x,1)–>(1,0)

样例输入
2
样例输出
2
-1 0 1
1
0 1
表示 x^2-1和x,进行两次得到结果(x^2-1,x)–>(x,-1)–>(-1,0)

解法

题目很长,比较难以理解.
数学题先推结论.
显然输入为n时,输出总是度数为n和n-1的两个多项式.
自然想到是否存在一个多项式序列an,使得ai和a(i+1)的gcd运算需要i步.
令a1=1 , a2=x , a3可以为x^2±1
多次实验发现a(i+2)=a(i+1)*x±ai可以递推.
如果150项内均有满足条件的式子,那么显然问题得解.

验证用代码

/* LittleFall : Hello! */#include <bits/stdc++.h>using namespace std;int save[160][160], tmp[160];//第一维deg 最高次,从0开始//第二维bit 每一位的系数,[0,deg]int main(void){    save[0][0] = 1; //常数1    save[1][1] = 1; //x+0    int outoutflag=1;    for(int deg = 2; deg < 160; deg++)    {        for(int bit = 1; bit <= deg; bit++)            save[deg][bit] = save[deg - 1][bit - 1];        int outflag = 0;        for(int k = -1; k <= 1; k += 2)        {            int flag = 1;            for(int bit = 0; bit <= deg - 2; bit++)            {                tmp[bit] = save[deg][bit] + save[deg - 2][bit] * k;                if(tmp[bit] <= -2 || tmp[bit] >= 2)                {                    flag = 0;                    break;                }            }            if(flag == 1)            {                for(int bit = 0; bit <= deg - 2; bit++)                    save[deg][bit] = tmp[bit];                outflag = 1;                break;            }        }        if(outflag == 0)        {            printf("unsuccesful in %d\n", deg);            outoutflag=0;            break;        }    }    if(outoutflag==1)        printf("succesful!" );    return 0;}

使用的是非常simple的搜索验证,甚至没有回溯.
验证成功,直接按验证的结果打表输出即可.

代码

/* LittleFall : Hello! */#include <bits/stdc++.h>using namespace std;int save[160][160], tmp[160];//第一维deg 最高次,从0开始//第二维bit 每一位的系数,[0,deg]int main(void){    save[0][0] = 1; //常数1    save[1][1] = 1; //x+0    for(int deg = 2; deg < 160; deg++)    {        for(int bit = 1; bit <= deg; bit++)            save[deg][bit] = save[deg - 1][bit - 1];        int outflag = 0;        for(int k = -1; k <= 1; k += 2)        {            int flag = 1;            for(int bit = 0; bit <= deg - 2; bit++)            {                tmp[bit] = save[deg][bit] + save[deg - 2][bit] * k;                if(tmp[bit] <= -2 || tmp[bit] >= 2)                {                    flag = 0;                    break;                }            }            if(flag == 1)            {                for(int bit = 0; bit <= deg - 2; bit++)                    save[deg][bit] = tmp[bit];                outflag = 1;                break;            }        }        if(outflag == 0)        {            printf("unsuccesful in %d\n", deg);            break;        }    }    int n;    scanf("%d", &n);    printf("%d\n", n );    for(int bit = 0; bit <= n; bit++)        printf("%d ", save[n][bit] );    printf("\n%d\n", n - 1 );    for(int bit = 0; bit <= n - 1; bit++)        printf("%d ", save[n - 1][bit] );    return 0;}

注意

程序中多次用到了一种控制流程如下

int flag=1;for(/*something*/){    /*something*/    if(/*something*/)    {        flag=0;        break;    }}if(flag)    /*something*/else    /*something*/

for循环部分实际为检验flag是否为1,同时可能有其它副作用.
在验证程序中,这样的部分嵌套了3次,对于编写代码带来很大的困难.
可以考虑使用函数等方式解决.

要敢于搜索和打表答案!积极写程序,不要用手搜!

原创粉丝点击