题解 [ARC141A] Periodic Number
一个不怎么需要动脑筋的做法,看了一圈题解区没有一篇题解提到,虽然效率不高但是还是来记录一下。
题意
给定一个正整数 \(N \ge 11\),求不超过 \(N\) 最大拥有循环节的数。
分析
因为答案有单调性,所以这种求不超过最大的问题可以二分答案转化为判定性问题。
外层循环枚举循环次数,内部二分重复的数即可。
单次时间复杂度 \(O(\log_{10}n\log_2{n})\),效率比较低。
代码
//the code is from chenjh
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
typedef long long LL;
LL n;
int w(const LL&x){return int(log10((long double)x))+1;}//求正整数位数。
LL p1[20];
LL f(const int x,int t){
LL ret=0;
int q=w(x);
if(q*t>18) return n+1;//位数太多直接返回 n+1。
while(t--) ret=ret*p1[q]+x;
return ret;
}
void solve(){
scanf("%lld",&n);
LL ans=0;
for(int i=2,mi=w(n);i<=mi;i++){
int l=1,r=p1[mi/i+1];
for(int mid;l<r;) f(mid=(l+r+1)>>1,i)>n?r=mid-1:l=mid;//二分找到最后一个小于等于 n 的数。
LL k=f(l,i);
k<=n&&(ans=max(ans,k));//取最大值。
}
printf("%lld\n",ans);
}
int main(){
p1[0]=1;
for(int i=1;i<=18;i++) p1[i]=p1[i-1]*10;
int T;scanf("%d",&T);
while(T--) solve();
return 0;
}

浙公网安备 33010602011771号