Soratosorato

ARC174D Digit vs Square Root 题解

Sorato·2024-03-20 13:03·21 次阅读

ARC174D Digit vs Square Root 题解

ARC174D Digit vs Square Root

题目大意#

给定 N,求有多少个正整数 x(1xN) 满足:在十进制表示下,xx 的前缀。

Solve#

很难直接手推性质,考虑用如下程序打表:

Copy
#include<bits/stdc++.h> #pragma GCC optimize(1,2,3,"Ofast","inline") using namespace std; #define int long long inline bool check(int x,int y) { stack<int>a,b; while(x) a.push(x%10),x/=10; while(y) b.push(y%10),y/=10; while(!a.empty()) { if(a.top()!=b.top()) return 0; a.pop();b.pop(); } return 1; } signed main() { int res=0,j,lst; for(int i=1;i<=1000000;i=-~i) { j=i;lst=res; while(check(sqrt(j*1.0),j)) j=-~j,res=-~res; if(j>i) printf("%lld~%lld: %lld~%lld\n",i,j-1,-~lst,res); i=j; } return 0; }

得到:

Copy
1~1: 1~1 80~80: 2~2 90~109: 3~22 9800~9800: 23~23 9900~10099: 24~223 998000~998000: 224~224 999000~1000999: 225~2224

我们不难可以发现这样的性质:

区间 [10i10i2,10i+10i21](即 1,90109,990010099)中的所有数 以及 10i2×10i2(即 80,9800,998000)满足条件(i 均为偶数)

仔细想一下,确实很对。

对于区间 [10i10i2,10i+10i21](imod2=0),我们将他拆成 [10i10i2,10i1][10i,10i+10i21] 来考虑:

  • 对于 [10i10i2,10i1],即 99009999,999000999999,显然他们开根向下取整都是 10i21,即 99,999,而且它们的前 i2 位也是 10i21。并且这些数的数位都是偶数,对于每个 i10i2 个。

  • 对于 [10i,10i+10i21],即 1000010099,10000001000999,它们开根向下取整都是 10i2,即 100,1000,而它们的前 i2 位也是 10i2。并且这些数的数位都是奇数,,对于每个 i10i2 个。

对于 10i2×10i2,即 80,9800,998000

  • (10i21)2=10i2×10i2+1,所以 10i2×10i2=10i22,即 80=8,9800=98,998000=998,显然 10i2210i2×10i2 的前缀,而不是 10i2×10i2x 的前缀。这些数的数位都是偶数,,对于每个 i1 个。

所以思路就很显然了:

  • 首先处理出 110i1 之间的所有符合条件的数的个数 sumi

  • 对于每次询问,判断出 N 的位数 m,无论 m 是奇数还是偶数,答案 ans 都可以先加上 sumi1

  • m 是偶数:如果 m10m2×10m2,令 ans 加上 1;如果 N10m10m2,令 ans 加上 N(10m2×10m2)+1

  • m 是奇数:令 ans 加上 min(N,10m1+10m21)10m1

Code#

Copy
#include<bits/stdc++.h> #pragma GCC optimize(1,2,3,"Ofast","inline") using namespace std; #define int long long inline int read() { short f=1; int x=0; char c=getchar(); while(c<'0'||c>'9') {if(c=='-') f=-1;c=getchar();} while(c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar(); return x*f; } inline int Get(int x) { int res=0; while(x) res=-~res,x/=10; return res; } int t,n,sum[20],mi[20]={1},ans; signed main() { for(int i=1;i<=18;i=-~i) { mi[i]=mi[i-1]*10; sum[i]=sum[i-1]+mi[i/2]; if(i%2==0) sum[i]=-~sum[i]; } // cout<<sum[3]; t=read(); while(t--) { n=read(); int res=Get(n); // cout<<res<<endl; ans=sum[res-1]; if(res%2==0) { // puts("into Case 1"); if(n>=mi[res]-2*mi[res/2]) ans=-~ans; if(n>=mi[res]-mi[res/2]) ans+=n-(mi[res]-mi[res/2])+1; } else ans+=min(n,mi[res-1]+mi[res/2]-1)-mi[res-1]+1; printf("%lld\n",ans); } return 0; }
posted @   Sorato  阅读(21)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
点击右上角即可分享
微信分享提示
目录