题目描述

小 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 }

 

posted @ 2019-10-28 22:35  Z-Y-Y-S  阅读(342)  评论(5编辑  收藏  举报