UVA 10061 How many zero's and how many digits ? (m进制,阶乘位数,阶乘后缀0)
2015-06-28 23:27
513 查看
题意:
给出两个数字a和b,求a的阶乘转换成b进制后,输出
(1)后缀中有多少个连续的0?
(2)数a的b进制表示法中有多少位?
思路:逐个问题解决。
设a!=k。 k暂时不用直接转成b进制。
(1)阶乘后缀0问题。先看这个十进制后缀0的例子:http://www.cnblogs.com/xcw0754/p/4604473.html
解法差不多,稍变化。 首先将b分解成若干质数(比如8={2*2*2})保存在一个集合A中(注意自然数的质数分解是唯一的),只要有一个序列A就能构成一个0,因为满b就进位,b可以表示成10,表示一个1*b+0。那么我们需要知道k中究竟有多少个集合A。将k也质数分解成集合B,在集合B中每次减去一个A,每成功减掉1个A就有1个后缀0。
直接求a!不是会爆吗?是的。将k进行质数分解和将{1~a}进行质数分解是一样的。那么就遍历[1,a]逐个进行分解,注意大于b的质数就不用去求了,其不可能用来组成b的。求完的质数的集合B应该是2有几个,3有几个,5有几个,7有几个...。如果集合A中需要4个2,那就看B中有多少个2,每两个2就可以组成一个后缀0,如果B中有5个2,那么就有2个0啦。
总之,这步需要将b质数分解成A,将[1,a]质数分解成集合B,再看B中有多少个A。
(2)阶乘的位数问题。
先举个例子: 一个三位数n满足102 <= n < 103
那么他的位数w 满足 w = log103 = 3。 因此只要求lgn 向下取整 +1就是位数后因为阶乘比如5阶乘的话是5 * 4 * 3 * 2 * 1。他的位数就满足lg5 * 4 * 3 * 2 * 1 = lg5 + lg4 + lg3 + lg2 + lg1 这里用相加的就不会超过数字上限。
当然这是十进制下得。如果是m进制下,就把log10n 换成logmn 就可以了。用高中知识:logm(n)的表示方法是 lgn / lgm。 这里有个double向下取整精度的问题要注意:转换成int时候,要floor(算出来的位数 + 1e-9) + 1. 注意:1e-9不要用变量存起来。
最后得出位数的计算方式为:floor( logmn + logm(n - 1) + ...+ logm1 + 1e-9) + 1.红色部分就是所要算的主要数字,用一个循环累加即可。
AC代码
给出两个数字a和b,求a的阶乘转换成b进制后,输出
(1)后缀中有多少个连续的0?
(2)数a的b进制表示法中有多少位?
思路:逐个问题解决。
设a!=k。 k暂时不用直接转成b进制。
(1)阶乘后缀0问题。先看这个十进制后缀0的例子:http://www.cnblogs.com/xcw0754/p/4604473.html
解法差不多,稍变化。 首先将b分解成若干质数(比如8={2*2*2})保存在一个集合A中(注意自然数的质数分解是唯一的),只要有一个序列A就能构成一个0,因为满b就进位,b可以表示成10,表示一个1*b+0。那么我们需要知道k中究竟有多少个集合A。将k也质数分解成集合B,在集合B中每次减去一个A,每成功减掉1个A就有1个后缀0。
直接求a!不是会爆吗?是的。将k进行质数分解和将{1~a}进行质数分解是一样的。那么就遍历[1,a]逐个进行分解,注意大于b的质数就不用去求了,其不可能用来组成b的。求完的质数的集合B应该是2有几个,3有几个,5有几个,7有几个...。如果集合A中需要4个2,那就看B中有多少个2,每两个2就可以组成一个后缀0,如果B中有5个2,那么就有2个0啦。
总之,这步需要将b质数分解成A,将[1,a]质数分解成集合B,再看B中有多少个A。
(2)阶乘的位数问题。
先举个例子: 一个三位数n满足102 <= n < 103
那么他的位数w 满足 w = log103 = 3。 因此只要求lgn 向下取整 +1就是位数后因为阶乘比如5阶乘的话是5 * 4 * 3 * 2 * 1。他的位数就满足lg5 * 4 * 3 * 2 * 1 = lg5 + lg4 + lg3 + lg2 + lg1 这里用相加的就不会超过数字上限。
当然这是十进制下得。如果是m进制下,就把log10n 换成logmn 就可以了。用高中知识:logm(n)的表示方法是 lgn / lgm。 这里有个double向下取整精度的问题要注意:转换成int时候,要floor(算出来的位数 + 1e-9) + 1. 注意:1e-9不要用变量存起来。
最后得出位数的计算方式为:floor( logmn + logm(n - 1) + ...+ logm1 + 1e-9) + 1.红色部分就是所要算的主要数字,用一个循环累加即可。
#include <bits/stdc++.h> #define LL long long using namespace std; const int N=2147483647; int has[999]; //哈希 int need[999]; //进制的分解 int second(int a,int b) //总位数 { double tmp=0.0; for(int i=2; i<=a; i++) tmp+=log10(i); if(b!=10) tmp/=log10(b); //转进制,10没必要转 return floor(tmp + 1e-9)+1; } int first(int a,int b) //后缀0个数 { memset(has,0,sizeof(has)); memset(need,0,sizeof(need)); for(int i=2; i<=a; i++) //先分解阶乘中每个数 { int t=i; for(int j=2; j<=t&&j<=b; j++) //质数为j { while(t%j==0) //能被j整除的,全部除掉 { has[j]++; t/=j; } } } int t=b; for(int i=2; i<=b; i++) //进制b进行分解 { while(t%i==0) { need[i]++; //需要质数的个数记录起来 t/=i; } } int cnt=N; for(int i=2; i<=b; i++) if(need[i]>0) cnt=min(cnt,has[i]/need[i]); //木桶原理,最低的一块木板起作用 return (cnt>=N?0:cnt); } int main() { //freopen("e://input.txt", "r", stdin); int a, b; while(~scanf("%d%d",&a,&b)) printf("%d %d\n", first(a,b), second(a,b)); return 0; } AC代码
AC代码
相关文章推荐
- 基于Spark机器学习和实时流计算的智能推荐系统
- Android推送进阶课程学习笔记
- Android Eclipse开发环境配置
- 杭电ACM1098——Ignatius's puzzle
- 基于Spark机器学习和实时流计算的智能推荐系统
- redis 数据类型详解 以及 redis适用场景场合
- 企业开发技术选型
- Longest Substring Without Repeating Characters - 哈希与双指针
- Git 学习总结
- mysql 表字段增、删、改
- 关于Android Studio SDK在线更新问题
- SPI总线小结
- node.js安装环境的检查和配置
- 当你不再依赖简历时会发生什么?
- VirtualBox 共享文件夹设置 及 开机自动挂载
- WPF命令
- 第一个servlet程序
- WPF listview 隐藏Header 列头
- 读取某个文件夹下的所有文件
- 22.AndroidManifest中original-package标签