• BZOJ 2742: [HEOI2012]Akai的数学作业


    2742: [HEOI2012]Akai的数学作业

    Time Limit: 10 Sec  Memory Limit: 128 MB
    Submit: 535  Solved: 226
    [Submit][Status][Discuss]

    Description

    这里是广袤无垠的宇宙这里是一泻千里的银河
    这里是独一无二的太阳系
    这里是蔚蓝色的地球
    这里,就是这里,是富饶的中国大陆!
    这里是神奇的河北大地
    这里是美丽的唐山
    这里是神话般的唐山一中
    这里是Akai曾经的教室
    黑板上还留有当年Akai做过的数学作业,其实也并不是什么很困难的题目:
     
    给出一个一元n次方程:
    a0 + a1x + a    2   x2 ++ anxn= 0
    求此方程的所有有理数解。
     
    Akai至今还深刻记得当年熬夜奋战求解的时光
    他甚至还能记得浪费了多少草稿纸
    但是却怎么也想不起来最后的答案是多少了
    你能帮助他么?

    Input

    第一行一个整数n。第二行n+1个整数,分别代表a    0 a n

    Output

    第一行输出一个整数t,表示有理数解的个数
    接下来t行,每行表示一个解
    解以分数的形式输出,要求分子和分母互质,且分母必须是正整数特殊的,如果这个解是一个整数,那么直接把这个数输出
    等价的解只需要输出一次
    所有解按照从小到大的顺序输出

    Sample Input

    3
    -24 14 29 6

    Sample Output

    3
    -4
    -3/2
    2/3

    HINT

    【数据范围】

    对于30%的数据,n<=10

    对于100%的数据,n <= 100,|a i| <= 2*10^7,an≠ 0

    Source

    [Submit][Status][Discuss]

    好神的一道HEOI题。

    据LH讲,有个定理叫做多项式高斯引理什么的,大概就是讲,复数域下的一个关于$x$的$n$次多项式$f(x)=a_{0}+a_{1}x+a_{2}x^{2}+a_{3}x^{3}+...+a_{n}x^{n}$一定可以分解成$n$个含$x$的一次多项式相乘,即$f(x)$一定存在一种形如$f(x)=prod{(b_{i}x+c_{i})}$的表示,其中每个式子都会产生一个复数域下的根(当然,这些根有可能重复)。这道题叫我们只用考虑有理数根,所以可以把式子改写为$f(x)=g(x)*prod{(b_{i}x+c_{i})}$的样子,其中g(x)是一个关于$x$的多项式,包含了所有的非有理数根,剩下的部分就表示了所有的有理数根。发现每个有理数根都能表示成$x_{i}=frac{c_{i}}{b_{i}}$,然后不难发现$f(x)=sum_{i=0}^{n}{a_{i}x^{i}}$中的$a_{0}$包含了所有的$c_{i}$,而$a_{n}$包含了有所的$b_{i}$,所以对于所有的合法有理数根$x_{i}=frac{c_{i}}{b_{i}}$,$c_{i}$一定是$a_{0}$的约数,$b_{i}$一定是$a_{n}$的约数。所以可以先处理出$a_{0}$和$a_{n}$的所有约数,然后暴力枚举$b_{i}$和$c_{i}$,$O(N)$check是否合法即可。check的方式是,对于$x=frac{p}{q}$,$f(x)=sum_{i=0}^{n}{a_{i}p^{i}q^{n-i}}$,在模意义下检查是否为$0$即可。

      1 #include <bits/stdc++.h>
      2 
      3 template <class T>
      4 T gcd(T a, T b)
      5 {
      6     return b ? gcd(b, a % b) : a;
      7 }
      8 
      9 typedef long long lnt;
     10 
     11 const int mxn = 105;
     12 const int mxm = 500005;
     13 const lnt mod = 1000000007;
     14 
     15 int n, s[mxn];
     16 
     17 struct number
     18 {
     19     int a, b, f;    // ans = a / b
     20 
     21     number(void) {};
     22     number(int x, int y, int g = 1)
     23         : a(x), b(y), f(g) {};
     24 
     25     void print(void)
     26     {
     27         if (f == -1)
     28             putchar('-');
     29         if (a % b)
     30             printf("%d/%d
    ", a, b);
     31         else
     32             printf("%d
    ", a / b);
     33     }
     34 }ans[mxm]; int tot;
     35 
     36 bool cmp(const number &A, const number &B)
     37 {
     38     if (A.f == -1 && B.f == +1)
     39         return true;
     40     if (A.f == +1 && B.f == -1)
     41         return false;
     42     if (A.f == +1 && B.f == +1)
     43         return 1LL * A.a * B.b < 1LL * B.a * A.b;
     44     if (A.f == -1 && B.f == -1)
     45         return 1LL * A.a * B.b > 1LL * B.a * A.b;
     46 }
     47 
     48 void leadingZeros(void)
     49 {
     50     int cnt = 0;
     51 
     52     while (!s[cnt])
     53         ++cnt;
     54 
     55     if (cnt)
     56     {
     57         n = n - cnt;
     58     
     59         for (int i = 0; i <= n; ++i)
     60             s[i] = s[i + cnt];
     61     
     62         ans[tot++] = number(0, 1);
     63     }
     64 }
     65 
     66 int divA[mxm], sizA;
     67 int divB[mxm], sizB;
     68 
     69 void divide(int x, int *div, int &siz)
     70 {
     71     if (x < 0)x = -x;
     72 
     73     siz = 0;
     74 
     75     int t = int(sqrt(x));
     76 
     77     for (int i = 1; i <= t; ++i)
     78         if (x % i == 0)
     79         {
     80             div[siz++] = i;
     81             div[siz++] = x / i;
     82         }
     83 
     84     if (t * t == x)--siz;
     85 }
     86 
     87 int powA[mxn];
     88 int powB[mxn];
     89 
     90 void check(lnt a, lnt b, lnt f)
     91 {
     92     powA[0] = powB[0] = 1LL;
     93 
     94     for (int i = 1; i <= n; ++i)
     95     {
     96         powA[i] = (powA[i - 1] * a) % mod;
     97         powB[i] = (powB[i - 1] * b) % mod;
     98     }
     99 
    100     lnt sum = 0, tmp;
    101 
    102     for (int i = 0; i <= n; ++i)
    103     {
    104         tmp = s[i];
    105         tmp = (tmp * powA[i]) % mod;
    106         tmp = (tmp * powB[n - i]) % mod;
    107 
    108         if (i & 1)tmp = (tmp * f + mod) % mod;
    109 
    110         sum = (sum + tmp) % mod;
    111     }
    112 
    113     if (sum == 0)ans[tot++] = number(a, b, f);
    114 }
    115 
    116 signed main(void) 
    117 {
    118     scanf("%d", &n);
    119 
    120     for (int i = 0; i <= n; ++i)
    121         scanf("%d", s + i);
    122 
    123     leadingZeros();
    124 
    125     divide(s[0], divA, sizA);
    126     divide(s[n], divB, sizB);
    127 
    128     for (int i = 0; i < sizA; ++i)
    129         for (int j = 0; j < sizB; ++j)
    130         {
    131             int a = divA[i];
    132             int b = divB[j];
    133 
    134             if (gcd(a, b) == 1)
    135             {
    136                 check(a, b, +1);
    137                 check(a, b, -1);
    138             }
    139         }
    140 
    141     std::sort(ans, ans + tot, cmp);
    142 
    143     printf("%d
    ", tot);
    144 
    145     for (int i = 0; i < tot; ++i)
    146         ans[i].print();
    147 }

    @Author: YouSiki

  • 相关阅读:
    防雪崩利器:熔断器 Hystrix 的原理与使用
    SpringBoot返回结果为null或空值不显示处理方法
    Tomca原理分析之责任链
    TOMCAT原理详解及请求过程
    RocketMQ支持事务消息机制
    ubuntu 安装rocketmq
    Monkey安装与配置教程
    Monkey通过安装包获取包名
    git使用笔记
    Linux解压命令
  • 原文地址:https://www.cnblogs.com/yousiki/p/6404149.html
Copyright © 2020-2023  润新知