【noip冲刺赛】:循环整数
2015-11-03 19:48
344 查看
【问题描述】
moreD 在学习完循环小数之后发现循环是个很美好的性质。自己只需要记住短短的循环
节以及循环次数(次数大于 1,且是整数)就可以记住整个数字了。
因为背诵数字变得方便了,moreD 决定背诵[L,R]内的所有循环的整数。moreD 的背诵
计划有 T 天,但是他不知道每天具体要背多少个数,请你帮助 moreD 计算出每天需要背诵
的数字个数。
如果 moreD 在某天遇到一个曾经背过的数字,他会义无反顾地重新背诵。
【输入格式】
第一行给出一个整数 T,表示 moreD 计划背诵 T 天的数字。
接下来 n 行,第 i 行给出 2 个整数 Li,Ri,表示 moreD 第 i 天的背诵计划。
【输出格式】
输出 T 行,每行一个整数,表示第 i 天 moreD 需要背诵的数字个数。
【输入输出样例】
circulate.in circulate.out
3
1 10000
55555 66666
10 100
108
2
9
【数据范围】
对于 30%的数据 T*MAX{Ri}<=2*10^6
对于 70%的数据 MAX{Ri}<=2*10^6
对于 100%的数据 T<=50000,1<=Li<=Ri<=2*10^18
【样例解释】
对于第 2 天,moreD 只需要背诵 55555,66666.
对于第 3 天,moreD 只需要背诵 11,22,33,44,55,66,77,88,99.
把一个区间[l,r]分成两个区间[1,l][1,r],然后分别计算各区间的数量,最后用右边的区间减去左边的区间即可。
至于中间查找的过程= =。。。我能说是找规律吗。。
moreD 在学习完循环小数之后发现循环是个很美好的性质。自己只需要记住短短的循环
节以及循环次数(次数大于 1,且是整数)就可以记住整个数字了。
因为背诵数字变得方便了,moreD 决定背诵[L,R]内的所有循环的整数。moreD 的背诵
计划有 T 天,但是他不知道每天具体要背多少个数,请你帮助 moreD 计算出每天需要背诵
的数字个数。
如果 moreD 在某天遇到一个曾经背过的数字,他会义无反顾地重新背诵。
【输入格式】
第一行给出一个整数 T,表示 moreD 计划背诵 T 天的数字。
接下来 n 行,第 i 行给出 2 个整数 Li,Ri,表示 moreD 第 i 天的背诵计划。
【输出格式】
输出 T 行,每行一个整数,表示第 i 天 moreD 需要背诵的数字个数。
【输入输出样例】
circulate.in circulate.out
3
1 10000
55555 66666
10 100
108
2
9
【数据范围】
对于 30%的数据 T*MAX{Ri}<=2*10^6
对于 70%的数据 MAX{Ri}<=2*10^6
对于 100%的数据 T<=50000,1<=Li<=Ri<=2*10^18
【样例解释】
对于第 2 天,moreD 只需要背诵 55555,66666.
对于第 3 天,moreD 只需要背诵 11,22,33,44,55,66,77,88,99.
把一个区间[l,r]分成两个区间[1,l][1,r],然后分别计算各区间的数量,最后用右边的区间减去左边的区间即可。
至于中间查找的过程= =。。。我能说是找规律吗。。
#include<cstdio>//将一个区间[l,r]分为[1,l]和[1,r]; 分别计算值 然后右边的减去左边的 #include<cstring> #include<algorithm> using namespace std; const int maxn=19; char a[20]; char b[20]; int n; long long num[20]; long long sum[20]; void prepare()//初始 { for(int i=1;i<maxn;i++) { long long p=9; for(int j=1;j<i;j++,p*=10) { if(i%j==0) { sum[j]=p; // printf("%d\n",p); for(int k=1;k<j;k++) { if(j%k==0) { sum[j]-=sum[k];// } } num[i]+=sum[j]; // printf("i=%d j=%d num=%lld sum=%lld\n",i,j,num[i],sum[j]); } } } } long long init(char a[])//字符串转化为数字 { long long rs=0; int n=strlen(a); for(int i=0;i<n;i++) { rs=rs*10+a[i]-'0'; } return rs; } int count_num(long long x) { int d[maxn]; int p=0;//p即为位数 while(x>0)//将每一位存到d里面 { d[++p]=x%10; x/=10; } int ans=0; for(int i=1;i<p;i++) { ans+=num[i]; // printf("i=%d num=%lld ans=%d\n",i,num[i],ans); } long long s=1; for(int j=1;j<p;j++,s*=10) { if(p%j==0) { long long t=0; for(int i=p;i>p-j;i--)// { t=t*10+d[i]; //printf("t=%d\n",t); } long long q=0; bool flag=false; for(int i=p-j;i>0;i--) { // printf("i=%d\n",i); q=q*10+d[i];// // printf("%d\n",q); if(i%j==1||j==1) { if(q<t) {//printf("--------------"); flag=true; }else if(q>t) break; q=0; } } sum[j]=t-s-flag+1; // printf("j=%d orz=%d\n",j,sum[j]); for(int k=1;k<j;k++) { if(j%k==0) { sum[j]-=sum[k]; } } ans+=sum[j]; } } return ans; } int main() { freopen("circulate.in", "r", stdin); freopen("circulate.out", "w", stdout); prepare(); scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%s %s",a,b); long long sb1=init(a); long long sb2=init(b); // printf("%lld %lld\n",sb1,sb2); long long ans=count_num(sb2)-count_num(sb1-1); //printf("sb2=%d sb1=%d\n",count_num(sb2),count_num(sb1)); printf("%lld\n",ans); } return 0; } /* 求一个数字区间内有循环节的数字个数: input: 3 1 10000 55555 66666 10 100 output: 108 2 9 */
相关文章推荐
- 64位CentOS6.5下安装hive
- Inna and New Matrix of Candies(CodeForces - 400B)
- lightoj 1224(trie)
- 醉醒间
- How GPUs Work
- linux kernel log 级别设置
- php字符串处理函数总结
- Oracle的基本操作
- 远程链接oracle-12519
- Adaboost与boosting
- Linux下安装JDK
- 【LeetCode OJ】Longest Substring Without Repeating Characters
- 表情匹配总数 DP SRM 671 div1 300 BearCries
- Android实战技巧:如何在ScrollView中嵌套ListView
- [GitHub]简单几步将你的项目托管到GitHub
- 基于RHCS+iSCSI+CLVM实现Web服务的共享存储集群架构
- Android测试 ---- Espresso + Jacoco
- 第七周 数据结构实践项目-对栈【项目5 -排队看病模拟】
- 20151103 IBM AIX oracle shutdown,shared pool分析
- 这些幽默只有程序员才懂?