Akai的数学作业

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

Description

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

Input

  第一行一个整数n。第二行n+1个整数,分别代表a0 到 an

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

Main idea

  给出一个一元n次方程:A0+A1*x+A2*x^2+…+An*x^n,求出这个方程的所有有理数解。

Solution

  这必然是一道数论题。首先我们发现了题目的一个非常重要的特征:求的是有理数解
  立马想到了分解因式,因为要的是有理数解,所以原方程肯定可以表示成:

  x就是q/p。

  然后再来思考一下。我们先从最简单的情况开始处理,也就是A0≠0,An≠0的情况。
  显然可以知道p一定是An分出来的,q一定是A0分出来的,那么一定有p是An的约数,q是A0的约数,那么这时候所有的情况就应该是

  仔细推一下式子,发现了一个规律:几个约数相乘的情况所表达出的集合和不考虑相乘情况的集合是一样的!那么处理就简单了很多。

  由于可能有前几项系数=0的情况,所以我们从A0的想法出发,找到第一个系数非0的项将这一项的约数存下来(如果不是A0的话则在答案中加一个0),然后从后往前找找到第一个非0的存下它的约数。然后O(约数个数)^2枚举任意两种情况的q/p放到原式里面判断(答案有可能是负数所以还要检查一下-q/p可不可行)然后在检查的时候发现了一个问题,数字要么精度误差过大要么就是爆出int范围了,我们想到了通分,分子分母同乘上p^n,避免了精度问题。

  以n=3的举个例子:将原式

  

  转化为

  然后我们就可以不管分母了,用这样的方法解决了精度问题。那么怎么解决爆int范围的问题呢?我们发现,在每次操作的时候都对一个质数取模的话错解的几率不是非常大,那么我们就可以大胆地取模几个质数来判断,如果不放心可以多取模几个。

  BearChild发现了一个神奇的质数:50033(如果使用这个质数的话是不需要用其余几个质数判断的)。

  这样进行累加和是否为0的判断,可行的话将每个答案存下来,然后sort一遍输出即可。

Code

 #include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
using namespace std; const int ONE=;
const int MOD=; int n;
int A[ONE];
int divisor[ONE][],num[];
int p[ONE];
int q[ONE];
int Repeat[ONE];
int cnt; struct power
{
int l,r;
int value;
}a[ONE]; int cmp(const power &a,const power &b)
{
return (double)a.l/a.r < (double)b.l/b.r;
} int get()
{
int res,Q=; char c;
while( (c=getchar())< || c>)
if(c=='-')Q=-;
if(Q) res=c-;
while((c=getchar())>= && c<=)
res=res*+c-;
return res*Q;
} int gcd(int a,int b)
{
int r=a%b;
while(r)
{
a=b;
b=r;
r=a%b;
}
return b;
} void Deal(int x,int PD)
{
for(int i=;i<=x;i++)
{
if(!(x%i)) divisor[++num[PD]][PD]=i;
}
} int Check(int x,int y)
{
p[]=q[]=;
for(int i=;i<=n;i++)
{
p[i]=(long long)p[i-]*y % MOD; q[i]=(long long)q[i-]*x % MOD;
} long long res=;
for(int i=;i<=n;i++)
{
res=(res+(long long)p[n-i]*q[i]*A[i]) % MOD;
} if(!res) return ;
return ;
} int main()
{
n=get();
for(int i=;i<=n;i++) A[i]=get();
if(A[]==)
{
a[++cnt].l=; a[cnt].r=;
}
for(int i=;i<=n;i++)
{
if(A[i])
{
Deal(abs(A[i]),);
break;
}
} for(int i=n;i>=;i--)
{
if(A[i])
{
Deal(abs(A[i]),);
break;
}
} for(int i=;i<=num[];i++)
for(int j=;j<=num[];j++)
{
int x=divisor[i][];
int y=divisor[j][];
if(gcd(x,y)!=) continue;
if(Check(x,y))
{
a[++cnt].l=x;
a[cnt].r=y;
}
if(Check(-x,y))
{
a[++cnt].l=-x;
a[cnt].r=y;
}
} sort(a+,a+cnt+,cmp);
printf("%d\n",cnt);
for(int i=;i<=cnt;i++)
{
if(a[i].r==) printf("%d\n",a[i].l);
else printf("%d/%d\n",a[i].l,a[i].r);
} }

【BZOJ2742】【HEOI2012】Akai的数学作业 [数论]的更多相关文章

  1. [BZOJ2742][HEOI2012]Akai的数学作业[推导]

    题意 给定各项系数,求一元 \(n\) 次方程的有理数解. \(n\leq 100\). 分析 设答案为 \(\frac{p}{q}\) ,那么多项式可以写成 \(a_0\frac{p}{q}+a_1 ...

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

    2742: [HEOI2012]Akai的数学作业 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 535  Solved: 226[Submit][S ...

  3. LuoguP5390 [Cnoi2019]数学作业(数论)

    转进制,然后发现贡献只有\(1_{(2)}\),取奇数个的子集方案是\(2^{n-1}\) #include <iostream> #include <cstdio> #inc ...

  4. 洛谷P3216 [HNOI2011] 数学作业 [矩阵加速,数论]

    题目传送门 数学作业 题目描述 小 C 数学成绩优异,于是老师给小 C 留了一道非常难的数学作业题: 给定正整数 N和 M,要求计算 Concatenate (1 .. N)Mod M 的值,其中 C ...

  5. BZOJ-2326 数学作业 矩阵乘法快速幂+快速乘

    2326: [HNOI2011]数学作业 Time Limit: 10 Sec Memory Limit: 128 MB Submit: 1564 Solved: 910 [Submit][Statu ...

  6. bzoj2326: [HNOI2011]数学作业

    矩阵快速幂,分1-9,10-99...看黄学长的代码理解...然而他直接把答案保存在最后一行(没有说明...好吧应该是我智障这都不知道... #include<cstdio> #inclu ...

  7. BZOJ 2326: [HNOI2011]数学作业( 矩阵快速幂 )

    BZOJ先剧透了是矩阵乘法...这道题显然可以f(x) = f(x-1)*10t+x ,其中t表示x有多少位. 这个递推式可以变成这样的矩阵...(不会用公式编辑器...), 我们把位数相同的一起处理 ...

  8. CJOJ 1331 【HNOI2011】数学作业 / Luogu 3216 【HNOI2011】数学作业 / HYSBZ 2326 数学作业(递推,矩阵)

    CJOJ 1331 [HNOI2011]数学作业 / Luogu 3216 [HNOI2011]数学作业 / HYSBZ 2326 数学作业(递推,矩阵) Description 小 C 数学成绩优异 ...

  9. [luogu P3216] [HNOI2011]数学作业

    [luogu P3216] [HNOI2011]数学作业 题目描述 小 C 数学成绩优异,于是老师给小 C 留了一道非常难的数学作业题: 给定正整数 N 和 M,要求计算 Concatenate (1 ...

随机推荐

  1. RTL8195AM开发板使用

    1. 本次使用RTL8195AM测试一下,原厂资源地址:https://os.mbed.com/platforms/Realtek-RTL8195AM/ 2. 由于板子支持mbed,所以把CON2连接 ...

  2. 活动的生命周期 Android

    1.运行程序 onCreate().onStart()和 onResume() 2.跳转到非弹框视图控制器 onPause()和 onStop() 返回上一个视图控制器(没被回收) onRestart ...

  3. MediaTypeListWidget->insertItem 添加的label没有填充单元格

    label没有填充满当前的item,但是主界面拉伸或者大小变化之后会填充当前的item 类似相关的问题我猜测都是因为子控件或者需要参考的控件的参考对象的大小在初始化的时候还没有完成最终的初始化,导致大 ...

  4. 失败的尝试,使用继承扩展数组,以及ES6的必要性

    我们都知道直接在原生对象上扩展对象是很不好的.所以prototype这样的库广受非议. 一些库,比如lodash采用了工具包形式的扩展方式,绕开了对象的继承. 由于es6的class的出现,我尝试以A ...

  5. 【紫书】(UVa12096) The SetStack Computer

    突然转进到第五章的low题目的原因是做到图论了(紫书),然后惊喜的发现第一题就做不出来.那么里面用到了这一题的思想,我们就先解决这题.当然,dp必须继续做下去,这是基本功.断不得. 题意分析 这条题真 ...

  6. Qt 汽车仪表再次编写,Widget,仪表显示,绘制界面

    感谢某网友提供UI让我练练手,上目前的效果 还在晚上,代码等后面在贴出来,就是出来显摆一下

  7. restAssured + TestNG测试接口,以下是一个get 请求。

    package Elaine.Test.G.APITest; import org.testng.Assert;import org.testng.annotations.BeforeTest;imp ...

  8. Python 套接字的使用 (1)

    获取设备名称和IPv4地址 socket.gethostname() socket.gethostbyname(host_name)   def print_machine_info(): host_ ...

  9. C语言关于“输入包含多行数据,请处理到文件结束”的问题

    今天,笔者在做本校ACM校赛网络赛的时候,遇到输入格式中有这样的要求:输入包含多行数据,请处理到文件结束.题目的逻辑很简单,主要功能代码很容易实现,但是题目中没有“明确”指出控制台中输入数据以什么方式 ...

  10. z 变换

    1. z 变换 单位脉冲响应为 \(h[n]\) 的离散时间线性时不变系统对复指数输入 \(z^n\) 的响应 \(y[n]\) 为 \[ \tag{1} y[n] = H(z) z^{n}\] 式中 ...