列表

详情


NC20001. [HEOI2012]AKAI的数学作业

描述

这里是广袤无垠的宇宙

这里是一泻千里的银河

这里是独一无二的太阳系

这里是蔚蓝色的地球

这里,就是这里,是富饶的中国大陆!

这里是神奇的河北大地

这里是美丽的唐山

这里是神话般的唐山一中

这里是 Akai 曾经的教室

黑板上还留有当年Akai做过的数学作业,其实也并不是什么很困难的题目: “ 给出一个一元n次方程: a0 + a1x + a2x2 +…+ anxn= 0 求此方程的所有有理数解。  ” 
Akai至今还深刻记得当年熬夜奋战求解的时光
他甚至还能记得浪费了多少草稿纸
但是却怎么也想不起来最后的答案是多少了
你能帮助他么?

输入描述

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

输出描述

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

示例1

输入:

3 
-24 14 29 6

输出:

3 
-4 
-3/2 
2/3

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++(g++ 7.5.0) 解法, 执行用时: 9ms, 内存消耗: 488K, 提交时间: 2022-11-04 23:39:38

#include <bits/stdc++.h>
#define IOS ios::sync_with_stdio(0), cin.tie(0), cout.tie(0)
using namespace std;

const int N = 1e8, mod = 1e9 + 7;

typedef long long LL;
typedef pair<int, int> PII;

int n;
int a0, an;
vector<int> a[2], v;
vector<double> b;
vector<PII> ans;

LL ksm(LL a, LL b)
{
    LL res = 1;
    while(b)
    {
        if(b & 1) res = res * a % mod;
        a = a * a % mod;
        b >>= 1;
    }
    return res;
}

int gcd(int a, int b)
{
    return !b ? a : gcd(b, a % b);
}

bool check(int p, int q)
{
    LL x = p * ksm(q, mod - 2) % mod;
    LL res = 0, nt = 1;

    for(int i = 0; i <= n; i ++)
    {
        res = res + nt * v[i] % mod, res %= mod;
        nt = nt * x % mod;
    }
    return (res + mod) % mod == 0;
}

bool cmp(PII a, PII b)
{
    return 1LL * a.first * b.second < 1LL * a.second * b.first;
}

void init(int x, int id)
{
    if(x < 0) x = -x;
    for(int i = 1; i * i <= x; i ++)
    {
        if(x % i) continue;
        a[id].push_back(i);
        if(i * i != x) a[id].push_back(x / i);
    }
}

int main(void)
{
    IOS;
    cin >> n;
    a0 = -N;
    for(int i = 0; i <= n; i ++)
    {
        int x;
        cin >> x;
        if(a0 == -N && x) a0 = x;
        an = x;
        v.push_back(x);
    }

    init(a0, 0), init(an, 1); 
    for(int i = 0; i < a[0].size(); i ++)
    {
        for(int j = 0; j < a[1].size(); j ++)
        {
            int p = a[0][i], q = a[1][j];
            if(gcd(p, q) == 1)
            {
                if(check(-p, q))
                    ans.push_back({-p, q});
                if(check(p, q))
                    ans.push_back({p, q});
            }
        }
    }
    
    if(check(0, 1)) ans.push_back({0, 1});
    sort(ans.begin(), ans.end(), cmp);
    
    cout << ans.size() << endl;
    for(int i = 0; i < int(ans.size()); i ++)
    {
        int p = ans[i].first, q = ans[i].second;
        if(q == 1)
            cout << p << endl;
        else 
            cout << p << "/" << q << endl;
    }
    return 0;
}

/*
a0 + a1x + a2x^2 + ... + anx^n = 0;
考虑 有理数 x = p / q, gcd(x, y) = 1;

a0 * q^n ≡ 0 (mod p)
an * p^n ≡ 0 (mod q)

枚举 a0 和 an 的约数
*/

C++14(g++5.4) 解法, 执行用时: 11ms, 内存消耗: 3064K, 提交时间: 2019-08-12 15:22:37

#include<bits/stdc++.h>

using namespace std;

typedef long long ll;

const int Mod = 1e9+7;
const double eps = 1e-7;

vector<int> div(int x){
    x = abs(x);
    vector<int> a;
    for(int i=1;i*i<=x;i++)
    {
        if( x%i == 0 )
        {
            a.push_back(i);
            if( i*i != x )
                a.push_back(x/i);
        }
    }
    return a;
}

ll mypow(ll a,ll b){
    ll inv = 1;
    while( b )
    {
        if( b&1 )  inv = inv*a%Mod;
        a = a*a%Mod;
        b >>= 1;
    }
    return inv;
}

int n;
int a[233];

vector<int> P,Q;

struct Hex{
    ll p,q;
    double x;
    Hex(ll p=0,ll q=0,double x=0):p(p),q(q),x(x){}
};

int tol,sum;
Hex ans[111110];

int dcmp(double x){
    if( fabs(x) <= eps )  return 0;
    return x > 0 ? 1 : -1;
}

bool cmp(Hex a,Hex b){
    return a.x < b.x;
}

int gcd(int a,int b){
    return b == 0 ? a : gcd(b,a%b);
}

bool calc(ll p,ll q){
    // cout<<p<<" "<<q<<endl;
    int x = p*mypow(q,Mod-2)%Mod;
    ll res = 0;
    ll pro = 1;
    for(int i=0;i<=n;i++)
    {
        res = (res + pro*a[i]%Mod)%Mod;
        pro = pro*x%Mod;
    }
    return (res + Mod)%Mod == 0;
}

void Out(Hex h){
    if( h.q == 1 )  printf("%lld\n",h.p);
    else printf("%lld/%lld\n",h.p,h.q);
    return ;
}

int main(){
    scanf("%d",&n);
    for(int i=0;i<=n;i++)
        scanf("%d",&a[i]);
    int l = 0;
    while( a[l] == 0 )  l++;
    P = div(a[l]);
    Q = div(a[n]);
    for(int i=0;i<P.size();i++)
        for(int j=0;j<Q.size();j++)
        {
            int p = P[i],q = Q[j];
            if( gcd(p,q) != 1 )  continue;
            if( calc(p,q) )  ans[tol++] = Hex(p,q,1.0*p/q);
            if( calc(-p,q) )  ans[tol++] = Hex(-p,q,-1.0*p/q);
        }
    if( calc(0,1) )  ans[tol++] = Hex(0,1,0);
    // cout<<tol<<endl;
    // cout<<ans[1].p<<" "<<ans[1].q<<endl;1
    if(tol == 0){puts("0");return 0;}
    sort(ans,ans+tol,cmp);
    sum = 1;
    for(int i=1;i<tol;i++)
        if( dcmp(ans[i].x-ans[i-1].x) != 0 )  sum++;
    printf("%d\n",sum);
    Out(ans[0]);
    for(int i=1;i<tol;i++)
        if( dcmp(ans[i].x - ans[i-1].x) != 0 )  Out(ans[i]);
    return 0;
}

C++11(clang++ 3.9) 解法, 执行用时: 7ms, 内存消耗: 416K, 提交时间: 2020-08-22 20:43:56

#include<cstdio>
#include<algorithm>
#include<cmath>
#define eps 1e-12
using namespace std;
typedef long double ld;
const int N = 105;
int a[N + 1];pair<int, int>p[N + 1];
int cmp(pair<int, int>x, pair<int, int>y){return 1ll * x.first * y.second < 1ll * y.first * x.second;}
int gcd(int x, int y){
	int r;
	while(y)r = x % y, x = y, y = r;
	return x;
}
int f(ld x, int n){
	int i;ld y;
	for(i = n, y = 0;i >= 0;i--)y = y * x + a[i];
	return abs(y) < eps;
}
int main(){
	int n, i, j, m, k, x, y;
	scanf("%d", &n);
	for(i = 0;i <= n;i++)scanf("%d", &a[i]);
	if(!n){
		if(a[0])printf("0");
		else printf("1\n0/1");
		return 0;
	}x = abs(a[m = 0]);
	if(!x){
		p[m = 1] = make_pair(0, 1);
		for(i = 1;i <= n && !a[i];i++);
		x = abs(a[i]);
		for(j = i;j <= n;j++)a[j - i] = a[j];
		n -= i;
	}y = abs(a[n]);
	if(!n){
		printf("1\n0/1");
		return 0;
	}
	for(i = 1;i <= x / i;i++)if(!(x % i))
		for(j = 1;j <= y / j;j++)if(!(y % j)){
			if(f((ld)i / j, n)){
				k = gcd(i, j);
				p[++m] = make_pair(i / k, j / k);
			}if(f(-(ld)i / j, n)){
				k = gcd(i, j);
				p[++m] = make_pair(-i / k, j / k);
			}
			if(f((ld)x / i / j, n)){
				k = gcd(x / i, j);
				p[++m] = make_pair(x / i / k, j / k);
			}if(f(-(ld)x / i / j, n)){
				k = gcd(x / i, j);
				p[++m] = make_pair(-x / i / k, j / k);
			}
			if(f((ld)i / (y / j), n)){
				k = gcd(i, y / j);
				p[++m] = make_pair(i / k, y / j / k);
			}if(f(-(ld)i / (y / j), n)){
				k = gcd(i, y / j);
				p[++m] = make_pair(-i / k, y / j / k);
			}if(f((ld)x / i / (y / j), n)){
				k = gcd(x / i, y / j);
				p[++m] = make_pair(x / i / k, y / j / k);
			}if(f(-(ld)x / i / (y / j), n)){
				k = gcd(x / i, y / j);
				p[++m] = make_pair(-x / i / k, y / j / k);
			}
		}sort(p + 1, p + m + 1, cmp);
	m = unique(p + 1, p + m + 1) - p - 1;
	printf("%d\n", m);
	for(i = 1;i <= m;i++)
		if(p[i].second == 1)printf("%d\n", p[i].first);
		else printf("%d/%d\n", p[i].first, p[i].second);
	return 0;
}

上一题