一元二次方程组膜下解

题目链接:Wannfly挑战赛4-E

题目描述:

题目描述

对于一个模意义下的一元二次方程:x+ ax + b = 0 (mod p),其中 p 是质数。

每次给定一组 a,b,p,问这个方程有没有整数解,有解输出“Yes”,无解输出“No”。

有 T 组询问。

输入描述:

输入第一行一个正整数T(T<=105),表示数据组数。
接下来T行每行三个非负整数a,b,p(0<=a,b9+7),p是质数,表示一组询问。

输出描述:

输出共T行,每行一个字符串“Yes”或“No”分别表示有解和无解。
示例1

输入

3
4 4 11
38946 243856 19260817
234876 791683756 1000000007

输出

Yes
Yes
No
题目思路:

 如果 p = 2,那么就把 0 和1分别带进去试一试就好。

如果 p > 2,那么p是奇质数,就可以把方程转化成 y*y = t (mod p)的形式,其中 t = (a/2)*(a/2)-b(mod p)。(注意 /2在膜意义下是乘以 2 的逆元),这样的话就变成了检验 t 在膜 p 意义下是否有二次剩余。

首先特判掉 t = 0 的情况,这个是显然有唯一解的。

之后如果有二次剩余,那么一定可以把 t 写成 g^(2k)的形式,其中 g 是 p 的一个原根,这样的话 t 肯定满足:t^((p-1)/2)=g^(k (p - 1))=1^k = 1。

相反,如果没有二次剩余,设 t =g^u ,那么 u 必然是奇数,所以 u ( p-1)/2 也不会是 p-1 的倍数, t^((p-1)/2)也不等于1 ,而会等于 -1 。

综上,我们就只需要看  t^((p-1)/2)是否等于 1 就可以判断 t 是否有二次剩余了。若 t 有二次剩余,即  t^((p-1)/2)= 1,则原方程有解,否则就无解。

代码:

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define ri(n) scanf("%d",&n)
#define oi(n) printf("%d\n",n)
#define rl(n) scanf("%lld",&n)
#define ol(n) printf("%lld\n",n)
#define rep(i,l,r) for(i=l;i<=r;i++)
#define rep1(i,l,r) for(i=l;i>=1;
    }
    return ans;
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        ll a,b,p;
        scanf("%lld%lld%lld",&a,&b,&p);
        if(p==2)
        {
            if(b%p==0||(1+a+b)%p==0)
                printf("Yes\n");
            else
                printf("No\n");
            continue;
        }
        if((4*b-a*a)%p==0)
            printf("Yes\n");
        else if(quick(a*a-4*b,(p-1)/2,p)==1)
            printf("Yes\n");
        else
            printf("No\n");
    }
    return 0;
}


你可能感兴趣的:(数论)