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. 一步一步构建手机WebApp开发——页面布局篇

    继上一篇:一步一步构建手机WebApp开发——环境搭建篇过后,我相信很多朋友都想看看实战案例,这一次的教程是页面布局篇,先上图: 如上图所示,此篇教程便是教初学者如何快速布局这样的页面.废话少说,直接 ...

  2. 13.0 Excel表格写入

    Excel表格写入 安装 xlutils 和 xlwt Excel写入输入 分两种方式: 第一种是向一张新表之中写入..这种不多说,我几乎没怎么用,直接贴代码 import xlwt Excel_na ...

  3. bam文件测序深度统计-bamdst

    最近接触的数据都是靶向测序,或者全外测序的数据.对数据的覆盖深度及靶向捕获效率的评估成为了数据质量监控中必不可少的一环. 以前都是用samtools depth 算出单碱基的深度后,用perl来进行深 ...

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

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

  5. Htmlemail邮件发送

    /** * * @param path //发送附件路径 * @param name //附件名称 * @param hostName //邮件服务器名称 * @param port //服务器端口 ...

  6. Leetcode 686.重复叠加字符串匹配

    重复叠加字符串匹配 给定两个字符串 A 和 B, 寻找重复叠加字符串A的最小次数,使得字符串B成为叠加后的字符串A的子串,如果不存在则返回 -1. 举个例子,A = "abcd", ...

  7. ThinkPHP自定义成功界面、失败界面、异常界面

    在ThinkPHP的手册中,附录里边的配置参考,有一个模板引擎设置. 或者在手册里面的控制器,跳转和重定向里面. 紧接着,就讲到了如何自定义这些界面. 将上诉的配置参数写到到配置文件里,修改路径到自己 ...

  8. MySQL 5.6查看数据库的大小

    1. use information_schema; 2. select concat(round(sum(data_length/1024/1024),2),'MB') as data from t ...

  9. 数据结构14——AC自动机

    一.相关介绍 知识要求 字典树Trie KMP算法 AC自动机 多模式串的字符匹配算法(KMP是单模式串的字符匹配算法) 单模式串问题&多模式串问题 单模就是给你一个模式串,问你这个模式串是否 ...

  10. springmvc项目搭建五-postgresql+easyui的数据显示

    上一篇虽然完成了页面的显示,但是是假数据,本篇添加了postgresql的数据库,将登陆的校验和数据的显示都通过数据库来完成. 我是在本地搭建了一个postgre的数据库,就先新建两张表吧,一个用于用 ...