求区间[a,b]之间的大数据的回文数个数解题报告

来源:互联网 发布:中国农业大学网络管理 编辑:程序博客网 时间:2024/05/19 20:44

一、题目描述。

有多组数据,每组一个a,b,求区间 [a,b]内有多少个回文数。a,b在int范围内。

二、解题思路。

按照常规的从a枚举到b再依次判断每个数是否为回文数显然是行不通的,所以我们需要用数学方法。

我们考虑分别求出[1,a-1] [1,b]之间有多少个回文数,然后将两者相减既是答案。


首先考虑位数为偶数的数,如1536,位数为四位,将它对半分为15和36,则当前半部分为14的时候,后两位可以取00到99之间的任意数,所以前两位从10到14都可以找到对应的后两位(如01,41)来形成回文数。此时我们只需考虑前两位是15的情况。观察知道后两位至少得是51才能与15形成回文数,而36<51,显然不行,也就是说1536只可形成前两位10到14这样5个回文数(1001,1111,1221,1331,1441)。求出了1000以上的回文数有多少个,再加上小于1000的回文数个数,既是[1,1536]之间回文数的个数。

所以,对于数abcd,大于1000时,我们只需比较cd与ba的大小,如果cd>=ba,则有(cd-10)+1个回文数,否则为cd-10个。

对于任意有2*n位数,谁t=a/(10^n)(其实t就是该数的前面一半)  ans=f[2*n-1]+t-10^(n-1)  或  ans=f[2*n-1]+t-10^(n-1)+1;


同理对于位数为奇数的数,如15368,只需比较368与351的大小,然后答案情况同上,(如abcde,比较cde与cba的大小)请读者自行思考。


三、参考代码。

#include <iostream>#include <cstdio>using namespace std;long long m,n,x,y;long long f[12]={0,9,18,108,198,1098,1998,10998,19998,109998,199998,1099998};    //预处理从1到10^i-1之间共有f[i]个回文数long long find(long long x){if (x==0) return 0;//边界情况if (x<10) return x;//小于10时每个数字都是一个回文数long long w,i,ans,t,na,a,b,nx;w=0;nx=x;while (nx)//求数x的位数{w++;nx/=10;}ans=f[w-1];//ans初始化t=1;for (int k=1;k<=(w/2);k++) t*=10;if (w%2==0)     //处理位数为偶数的数{a=(x/t);b=(x%t);t=t/10;ans=ans+(a-t);na=0;while (a){na=na*10+a%10;a/=10;}}else           //处理位数为奇数的数{a=(x/t);t*=10;b=(x%t);t=t/10;ans=ans+(a-t);na=0;while (a){na=na*10+a%10;a/=10;}}if (b>=na) ans++;            return ans;}int main(){//freopen("x.in","r",stdin);//freopen("x.out","w",stdout);while (cin>>m>>n){m=m-1;x=find(m);  //求1到m有多少个回文数y=find(n);  //求1到n有多少个回文数cout<<y-x<<endl;}} 

0 0
原创粉丝点击