[BZOJ2742/Luogu4598][HEOI2012]Akai的數學做業

題目連接:php

BZOJ2742測試

Luogu4598ui

好想吐槽某谷評分制度。。爲何我評個藍以後從紫變成了黑。。。spa

首先,設解$x=\frac{p}{q}(Gcd(p,q)=1)$code

那麼就有$\sum_{i=0}^n\limits a_ix^i=0$ip

$\sum_{i=0}^n\limits a_i(\frac{p}{q})^i=0$get

乘以$q_i$通分:$\sum_{i=0}^n\limits a_ip^iq^{n-i}=0$it

那麼能夠推導出:io

$\sum_{i=0}^n\limits a_ip^iq^{n-i}\equiv a_0q^n\equiv 0(mod\ p)$Markclass

$\sum_{i=0}^n\limits a_ip^iq^{n-i}\equiv a_np^n\equiv 0(mod\ q)$

由於$p,q$互質那麼獲得結論:$p|a_0,q|a_n$

暴力枚舉$p,q$代入方程判斷合法便可。

如何判斷?能夠選取一個模數看兩邊在同餘系下是否相同(詳情能夠參考Luogu2312解方程

不放心能夠多選幾個進行測試。

還有幾個須要注意的問題:

$a_0=0$怎麼辦?怎麼枚舉$p$?

找到一個最小的$i$使得$x_i\not=0$,那麼枚舉$x_i$的因子便可(此時上文推導Mark處的$mod\ p$就變成了$mod\ p^{i+1}$)

第二是要判斷負數解,即$-\frac{p}{q}$

最後須要特判最終解$x=\frac{p}{q}=0$的狀況(即$a_0=0$)。

時間複雜度:能過

代碼:

#include <cstdio>
#include <vector>
#include <algorithm>
typedef long long ll;

inline int Abs(const int x){return x>=0?x:-x;}
int Gcd(const int a,const int b){return b?Gcd(b,a%b):a;}
ll Pow(ll a,ll b,const int p)
{
	ll Res=1;
	for(;b;b>>=1,a=a*a%p)
		if(b&1)Res=Res*a%p;
	return Res%p;
}
int n,a[105];
const int Mod=1000000007;
struct Fraction
{
	int p,q;
	inline bool operator<(const Fraction &o)const
	{return (double)p/q<(double)o.p/o.q;}//分數 p爲分子 q爲分母
};
std::vector<int> Factor[2];//a[0](a[i])和a[n]的因子
std::vector<Fraction> Answer;

void Get_Factor(const int Number,std::vector<int> &Result)//求Number的因子,存放在Result中
{for(int i=1;i<=Number;++i)if(Number%i==0)Result.push_back(i);}//O(N)遍歷已經足夠

void Check_Answer(int p,int q)//判斷解可行性
{
	ll g=Gcd(Abs(p),Abs(q)),xs=1,Value=0,x=p*Pow(q,Mod-2,Mod)%Mod;
	if(g>1)return;//防止解重複,如1/2,2/4,3/6...
	for(int i=0;i<=n;++i)
	{
		Value=(Value+a[i]*xs)%Mod;
		xs=xs*x%Mod;
	}
	if(!Value)Answer.push_back((Fraction){p,q});
}

int main()
{
	scanf("%d",&n);
	for(int i=0;i<=n;++i)scanf("%d",&a[i]);
	for(int i=0;i<=n;++i)
		if(a[i]!=0)Get_Factor(Abs(a[i]),Factor[0]),i=n;
	Get_Factor(Abs(a[n]),Factor[1]);
	if(!a[0])Answer.push_back((Fraction){0,1});
	for(int i=0;i<(int)Factor[0].size();++i)
		for(int j=0;j<(int)Factor[1].size();++j)
		{
			Check_Answer(+Factor[0][i],Factor[1][j]);
			Check_Answer(-Factor[0][i],Factor[1][j]);
		}
	std::sort(Answer.begin(),Answer.end());
	printf("%d\n",(int)Answer.size());//按要求輸出解
	for(int i=0;i<(int)Answer.size();++i)
		if(Answer[i].q==1)printf("%d\n",Answer[i].p);
		else printf("%d/%d\n",Answer[i].p,Answer[i].q);
	return 0;
}
相關文章
相關標籤/搜索