题
题目描述
小 X 遇到了一道题:
给定自然数 a,ba,ba,b,求满足下列条件的自然数对 (x,y)的个数:
y^2−x^2=ax+b
他不会,只好求助于精通数学的你。
如果有无限多个自然数对满足条件,那么你只需要输出 inf
即可。
输入格式
一行两个整数 a,b。
输出格式
如果个数有限,一行一个整数,表示个数。
如果个数无限,一行一个字符串 inf
。
输入输出样例
输入 #1
5 15
输出 #1
1
输入 #2
4 4
输出 #2
inf
输入 #3
12 6
输出 #3
0
输入 #4
96 96
输出 #4
7
输入 #5
10000 9999997
输出 #5
6
对于100%数据,a<=10^8,b<=10^15
似乎鸽了很久
$$y^2-x^2=ax-b$$
有$$y^2=x^2+ax+b$$
$$y^2=(x+{a/2})^2+b-a^2/4$$
$$4y^2=(2*x+a)^2+4b-a^2$$
$$a^2-4b=(2x-2y+a)(2x+2y+a)$$
令$$A=2x-2y+a,B=2x+2y+a$$
有$$x=(A+B-2*a)/4,y=(B-A)/2$$
由于x,y为整数,所以对于$$S=a^2-4b=AB$$
A和B模4的值相同
根据x的表达式,发现要根据a的奇偶性特殊判断
至于特殊情况包括如下:
S=0时,有$$(2x+a)^2=y^2$$输出inf
S<0时将一个因数取负再带入x的表达式(A和B都可以,这是显然的)
所以枚举S的因数并判断即可,复杂度$$O(sqrt(S))$$
由于常数比较大,所以%4用&3代替
菜鸡已经一年多没搞竞赛了,啥也不会,巨佬们就当看个热闹,如有错误,望轻喷
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<cmath> 6 using namespace std; 7 long long ans,a,b,S,k1,k2,k3,k4,sqr; 8 int flag,sign; 9 int main() 10 {int i; 11 scanf("%lld%lld",&a,&b); 12 S=a*a-4*b; 13 if (S==0) 14 { 15 cout<<"inf"; 16 return 0; 17 } 18 flag=0; 19 if (S<0) flag=1,S=abs(S); 20 if (a&1) sign=1; 21 else sign=0; 22 //cout<<sqrt(S)<<endl; 23 sqr=sqrt(S); 24 for (i=1;i<=sqr;i++) 25 if (S%i==0) 26 { 27 //cout<<i<<' '<<S/i<<' '<<i%4<<' '<<S/i%4<<endl; 28 k4=(i+S/i);k3=(S/i-i); 29 k1=i&3;k2=(S/i)&3; 30 if (flag) 31 { 32 k1=(4-k1)&3; 33 if (((k2-k1)&3)==0&&((((k1+k2)/2)&1)==sign)&&k3>=2*a) 34 ans++; 35 } 36 else 37 if (((k2-k1)&3)==0&&((((k1+k2)/2)&1)==sign)&&k4>=2*a) 38 ans++; 39 } 40 cout<<ans; 41 }