No more tricks, Mr Nanguo
题解
板子题...
首先,我们可以枚举y(毕竟y要小些)来求出一组最小的正整数解的x,y。不会T的,毕竟y很小。
由于Pell方程有着,
的迭代公式,我们可以通过递推将其求出第k组解。
关于上面迭代公式的证明:
证毕。
于是,我们又惊奇地发现上面的那个式子可以转化成矩阵快速幂求解。即:
,于是,就可以通过矩阵快速幂求解了。
其实还可以用连分数的方法去求第1组特解,不过不知道为什么要比暴力慢一些。
源码
暴力的代码
#include<cstdio>
#include<cmath>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<vector>
#include<queue>
#include<map>
#include<set>
#include<bitset>
#include<stack>
using namespace std;
typedef long long LL;
const int mo=8191;
typedef pair<int,int> pii;
template<typename _T>
void read(_T &x){
_T f=1;x=0;char s=getchar();
while(s>'9'||s<'0'){if(s=='-')f=-1;s=getchar();}
while('0'<=s&&s<='9'){x=(x<<3)+(x<<1)+(s^48);s=getchar();}
x*=f;
}
template<typename _T>
_T Fabs(_T x){return x<0?-x:x;}
int n,k;
struct matrix{
int n,m,c[2][2];
matrix(){n=m=0;memset(c,0,sizeof(c));}
matrix operator * (const matrix &rhs)const{
matrix res;res.n=n;res.m=rhs.m;
for(int i=0;i<n;i++)
for(int k=0;k<m;k++)
for(int j=0;j<rhs.m;j++)
(res.c[i][j]+=c[i][k]*rhs.c[k][j]%mo)%=mo;
return res;
}
};
matrix qkpow(matrix a,int s){
matrix res;res.n=a.n;res.m=a.n;
for(int i=0;i<a.n;i++)res.c[i][i]=1;
while(s){if(s&1)res=res*a;a=a*a;s>>=1;}
return res;
}
signed main(){
while(scanf("%d %d",&n,&k)!=EOF){
int t=floor(sqrt(1.0*n)),x,y=1;
if(t*t==n){puts("No answers can meet such conditions");continue;}
for(;;y++){x=floor(sqrt(n*y*y+1));if(x*x-n*y*y==1)break;}
matrix A,B;
A.n=2;A.m=1;A.c[0][0]=x;A.c[1][0]=y;
B.n=B.m=2;B.c[0][0]=B.c[1][1]=x;B.c[1][0]=y;B.c[0][1]=n*y;
A=qkpow(B,k-1)*A;
printf("%d\n",A.c[0][0]);
}
return 0;
}
连分数的代码
#include<cstdio>
#include<cmath>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<vector>
#include<queue>
#include<map>
#include<set>
#include<bitset>
#include<stack>
using namespace std;
typedef long long LL;
const int mo=8191;
typedef pair<int,int> pii;
template<typename _T>
void read(_T &x){
_T f=1;x=0;char s=getchar();
while(s>'9'||s<'0'){if(s=='-')f=-1;s=getchar();}
while('0'<=s&&s<='9'){x=(x<<3)+(x<<1)+(s^48);s=getchar();}
x*=f;
}
template<typename _T>
_T Fabs(_T x){return x<0?-x:x;}
int n,k;
struct matrix{
int n,m,c[2][2];
matrix(){n=m=0;memset(c,0,sizeof(c));}
matrix operator * (const matrix &rhs)const{
matrix res;res.n=n;res.m=rhs.m;
for(int i=0;i<n;i++)
for(int k=0;k<m;k++)
for(int j=0;j<rhs.m;j++)
(res.c[i][j]+=c[i][k]*rhs.c[k][j]%mo)%=mo;
return res;
}
};
matrix qkpow(matrix a,int s){
matrix res;res.n=a.n;res.m=a.n;
for(int i=0;i<a.n;i++)res.c[i][i]=1;
while(s){if(s&1)res=res*a;a=a*a;s>>=1;}
return res;
}
LL a[20005];
bool pell_minimum_solution(LL n,LL &x0,LL &y0){
LL n1=(LL)sqrt((double)n),b=n1,c=1;double sq=sqrt(n);
if(n1*n1==n)return false;int i=0;a[i++]=n1;LL p=1,q=0;
do{
c=(n-b*b)/c;double tmp=(sq+b)/c;
a[i++]=(LL)(floor(tmp));b=a[i-1]*c-b;
}while(a[i-1]!=2LL*a[0]);
for(int j=i-2;j>=0;j--){LL t=p;p=q+p*a[j];q=t;}
if(i&1)x0=p,y0=q;
else x0=2ll*p*p+1LL,y0=2ll*p*q;
return 1;
}
signed main(){
while(scanf("%d %d",&n,&k)!=EOF){
int t=floor(sqrt(1.0*n));
if(t*t==n){puts("No answers can meet such conditions");continue;}
LL x,y;bool g=pell_minimum_solution(n,x,y);
matrix A,B;
A.n=2;A.m=1;A.c[0][0]=x;A.c[1][0]=y;
B.n=B.m=2;B.c[0][0]=B.c[1][1]=x;B.c[1][0]=y;B.c[0][1]=n*y;
A=qkpow(B,k-1)*A;
printf("%d\n",A.c[0][0]);
}
return 0;
}