P7779 『JROI-2 / Stoi2039』等你下课题解
本题解是基于 VinstaG173 的题解所做的一些补充和改进。
题目要求的是所有
我们设
- 因为当
k\in Z_{\ge1} 的时候,即d 为平方数的时候,这个不等式非常好解。因为当y\ge 1 的时候,x+k\cdot y\ge1 ,所以x-k\cdot y\ge1 。
于是我们得到
当
- 当
k 是无理数的时候,我们可以用连分数来解决这个问题。
先来介绍一下
形如
假设
所以
且
况且,我们还可以用连分数来求解
我们现在要处理的是
因为
接下来就是如何求二次无理数的连分数和过渡数:
请阅读连分数这篇博客里面不失精度的求无限连分数的方法。
我们要求的是所有过渡数的和,而且每一种数我们只能计算一次。因为我们求得的过渡数都是正的,但是我们不能保证
因为如果循环节是奇数,那么它下一次循环的时候,奇数次位置上的数会跑到偶数次位置上来,所以如果循环节是奇数,那么所有奇数次上的数都要再加一遍。
代码
#include<bits/stdc++.h>
using namespace std;
const int MaxN=2e6+5;
const int MaxD=1e4+5;
const int MaxK=1414;
int T,d,vis[MaxN],state[MaxK+5],a[MaxD],c[MaxD],k[MaxD],cnt,ans,sk,ssk;
int main(){
for(register int i=1;i<=MaxK;i++){
vis[i*i]=1;
}
scanf("%d",&T);
while(T--){
scanf("%d",&d);
sk=sqrt(d);
ssk=sqrt(sk);
cnt=ans=0;
for(register int i=1;i<=ssk;i++){
ans+=i*i;
state[i*i]=1;
}
if(!vis[d]){
a[0]=sk;
c[0]=1;
k[0]=0;
while(a[cnt]!=sk*2){
k[cnt+1]=a[cnt]*c[cnt]-k[cnt];
c[cnt+1]=(d-k[cnt+1]*k[cnt+1])/c[cnt];
a[cnt+1]=(sk+k[cnt+1])/c[cnt+1];
cnt++;
if(!(cnt&1)){
if(c[cnt]<=sk){
if(!state[c[cnt]]){
ans+=c[cnt];
state[c[cnt]]=1;
}
}
}
}
if(cnt&1){
for(register int i=1;i<=cnt;i+=2){
if(c[i]<=sk){
if(!state[c[i]]){
ans+=c[i];
state[c[i]]=1;
}
}
}
}
for(register int i=1;i<=sk;i++){
state[i]=0;
}
}
printf("%d\n",ans);
}
return 0;
}