BZOJ 2742: [HEOI2012]Akai的数学作业
2742: [HEOI2012]Akai的數學作業
Time Limit: 10 Sec??Memory Limit: 128 MBSubmit: 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 nOutput
第一行輸出一個整數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\n", a, b); 31 else 32 printf("%d\n", 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\n", tot); 144 145 for (int i = 0; i < tot; ++i) 146 ans[i].print(); 147 }?
@Author: YouSiki
轉載于:https://www.cnblogs.com/yousiki/p/6404149.html
總結
以上是生活随笔為你收集整理的BZOJ 2742: [HEOI2012]Akai的数学作业的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: STL:大小写字母转换、字符转数字、ch
- 下一篇: 峰谷序列