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. Android ANR 分析

    首先贴一下trace 文件 Process: com.oppo.reader PID: 20358 Time: 2933175644_1545041895232 Flags: 0x38d83e44 P ...

  2. leetcode笔记--3 Niim game

    question: You are playing the following Nim Game with your friend: There is a heap of stones on the ...

  3. windows系统下npm升级的正确姿势以及原理

    本文来自网易云社区 作者:陈观喜 网上关于npm升级很多方法多种多样,但是在windows系统下不是每种方法都会正确升级.其中在windows系统下主要的升级方法有以下三种: 首先最暴力的方法删掉no ...

  4. AGV小车典型设计算法及应用

    1. AGV小车的发展背景 在现代化工业的发展中,提倡高效,快速,可靠,提倡将人从简单的工作中解放出来.机器人逐渐替代了人出现在各个工作岗位上.机器人具有可编程.可协调作业和基于传感器控制等特点,自动 ...

  5. BZOJ 4408 FJOI2016 神秘数 可持久化线段树

    Description 一个可重复数字集合S的神秘数定义为最小的不能被S的子集的和表示的正整数.例如S={1,1,1,4,13},1 = 12 = 1+13 = 1+1+14 = 45 = 4+16 ...

  6. HDU 4722 Good Numbers(位数DP)(2013 ACM/ICPC Asia Regional Online ―― Warmup2)

    Description If we sum up every digit of a number and the result can be exactly divided by 10, we say ...

  7. for循环再探

    摘要:for循环头的组成.for的执行流程 一.for 语句的组成 0. 举个例子 for (int val = 1; val <= 10; ++val) sum += val; 1. 循环头的 ...

  8. webmagic 二次开发爬虫 爬取网站图片

    webmagic的是一个无须配置.便于二次开发的爬虫框架,它提供简单灵活的API,只需少量代码即可实现一个爬虫. webmagic介绍 编写一个简单的爬虫 webmagic的使用文档:http://w ...

  9. java第七笔记

  10. java连接mysql底层封装

    package com.dao.db; import java.sql.Connection; import java.sql.SQLException; /** * 数据库连接层MYSQL * @a ...