zoukankan      html  css  js  c++  java
  • [BZOJ2742/Luogu4598][HEOI2012]Akai的数学作业

    题目链接:

    BZOJ2742

    Luogu4598

    好想吐槽某谷评分制度。。为什么我评个蓝之后从紫变成了黑。。。

    首先,设解(x=frac{p}{q}(Gcd(p,q)=1))

    那么就有(sum_{i=0}^nlimits a_ix^i=0)

    (sum_{i=0}^nlimits a_i(frac{p}{q})^i=0)

    乘以(q_i)通分:(sum_{i=0}^nlimits a_ip^iq^{n-i}=0)

    那么可以推导出:

    (sum_{i=0}^nlimits a_ip^iq^{n-i}equiv a_0q^nequiv 0(mod p))Mark

    (sum_{i=0}^nlimits a_ip^iq^{n-i}equiv a_np^nequiv 0(mod q))

    因为(p,q)互质那么得到结论:(p|a_0,q|a_n)

    暴力枚举(p,q)代入方程判断合法即可。

    如何判断?可以选取一个模数看两边在同余系下是否相同(详情可以参考Luogu2312解方程

    不放心可以多选几个进行测试。

    还有几个需要注意的问题:

    (a_0=0)怎么办?怎么枚举(p)

    找到一个最小的(i)使得(x_i ot=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
    ",(int)Answer.size());//按要求输出解
    	for(int i=0;i<(int)Answer.size();++i)
    		if(Answer[i].q==1)printf("%d
    ",Answer[i].p);
    		else printf("%d/%d
    ",Answer[i].p,Answer[i].q);
    	return 0;
    }
    
  • 相关阅读:
    Java中顺序、并行与并发
    Java设计模式之Iterator
    渗透基础流程思路丶技巧丶与总结
    阿里巴巴Java开发手册之并发处理注意事项
    Java中Thread方法启动线程
    IOCP之客户端及消息传递
    IOCP简单实现
    JAVA 递归线程池测试 ExecutorService / ForkJoinPool
    TCP与UDP的一些心得
    七.badboy检查点和参数化
  • 原文地址:https://www.cnblogs.com/LanrTabe/p/10497673.html
Copyright © 2011-2022 走看看