math
题目:
给定一个n,求解在n的范围,有多少对x,y满足xy+1|xx+yy,(ps:人话,满足xy+1是xx+yy的因子),询问1e5次,n的范围1e18。
解题思路
方程拿到手毫无思路,尝试打表找找规律,发现(x,xxx)一定是一组解。回到题目,列出一个方程k*(xy+1)=xx+yy。将x作为定制,求解y。通过伟达定理:y+y’=kx,yy’=xx-k。不妨设y>=x,那么可以知道(x,y’)为另一组解,并且0<=y’<=x。即另一组解为(x,ky’-x)可以发现其具有递减性,当y;=0时递推结束,将y=0带入到方程中,发现被k=x*x。
那么反向递推就可以求解出所有解。同时可以发现总数的范围在1e6这个数量级,可以通过打表存到vector中,在利用二分快速求救,时间复杂度o(1e6+log(n)).
code
#include<bits/stdc++.h>
using namespace std;
#define ll __int128
vector<ll>a;
void init()
{
a.push_back(1);
for(ll i=2;i<=1e6;i++)
{
ll x=i,y=i*i*i,k=i*i;
a.push_back(y);
while(y<=1e18)
{
ll tmp=y;
y=k*y-x;
x=tmp;
if(y<=1e18)a.push_back(y);
}
}
sort(a.begin(),a.end());
}
void solve()
{
long long n;
cin>>n;
int l=0,r=a.size()-1,ans=-1;
while(l<=r)
{
int mid=(l+r)>>1;if(a[mid]<=n)ans=mid,l=mid+1;else r=mid-1;
}
cout<<ans+1<<endl;
}
int main()
{
ios::sync_with_stdio(false);
int t;
cin>>t;
init();
//for(int i=0;i<=100;i++)cout<<(long long)a[i]<<endl;
while(t--)solve();
return 0;
}