bzoj 3552: 最右非零的数 && hduoj 1066: Last non-zero Digit in N!(求N!的最后一个非0位)
2016-06-29 19:18
260 查看
3552: 最右非零的数
Time Limit: 1 Sec Memory Limit: 128 MBSubmit: 89 Solved: 27
[Submit][Status][Discuss]
Description
给出正整数N(可能有前导0),请求出N!最右非零的数位的值。Input
第一行一个数T表示数据组数下接T行每行一个数N表示一组数据
Output
对于每组数据,输出一行一个数表示这组数据的答案Sample Input
25
4
Sample Output
24
思路与公式:
1:n!的尾部的"0"全部来自因子5和因子2(一对5和2产生一个0),如果把这些因子去掉,则可符合要求(2的个数
明显多于5的个数)
2:设F(n)为答案所要求的数,G(n)为1,2…n中将5的倍数的数换成1后的各项乘积,G(15)=1*2*3*4*1*6*7*8*9*
1*11*12*13*14*1(G(n)%10必不为0),则可推出以下两个公式
① n! = (n/5)! * 5^(n/5) * G(n) ② F(n!) = F((n/5)!) * F[5^(n/5) * G(n)] (可以递归)
3:根据②可知F[5^(n/5) * G(n)] = F[G(n)/(2^(n/5))],其中G(n)/(2^(n/5))可找到规律
4:枚举可找到上述规律为Mp[20] = {1,1,2,6,4,2,2,4,2,8,4,4,8,4,6,8,8,6,8,2}(20一循环)这样就可以算出答案啦
PS:
n<=19 ---- G
= data
n>=20 ---- G
= data[n%20]
n过大,这里用字符串处理
#include<stdio.h>
#include<string.h>
char str[10005];
int a[10005], Mp[20] = {1,1,2,6,4,2,2,4,2,8,4,4,8,4,6,8,8,6,8,2}; /*这个是F[5^(n/5)*G(n)]的前20(0-19)项,后面循环*/
int main(void)
{
int T, len, ret, i, c;
scanf("%d", &T);
while(T--)
{
scanf("%s", str);
len = strlen(str);
for(i=len-1;i>=0;i--)
a[len-1-i] = str[i]-'0'; /*将n的每一位存入数组a[],其中a[0]是最低位,a[len-1]是最高位*/
ret = 1;
while(len!=0) /*用循环代替递归*/
{
c = 0;
ret = ret*Mp[a[1]%2*10+a[0]]%10; /*"a[1]%2*10+a[0]"是计算n%20的值*/
for(i=len-1;i>=0;i--)
{
c = c*10+a[i]; /*计算n除以5之后的值,并将其存入(覆盖)a[]*/
a[i] = c/5;
c %= 5;
}
if(a[len-1]==0) /*如果最高位是0,去掉最高位*/
len--;
}
if(strcmp(str, "1")==0 || strcmp(str, "0")==0)
printf("1\n");
else
printf("%d\n", ret);
}
return 0;
}
相关文章推荐
- java 数组与链表的嵌套使用(数组链表--数据结构)
- android 聊天列表页面的时间显示问题--1(星期显示,暂无分块)
- 兼容html5方案
- 【NOIP2013模拟联考5】军训(training) 题解+代码
- Shell脚本中调用另外一个脚本的方法
- Linux cp 实现强行覆盖
- js数组 插入和删除指定位置
- linux存储技术设备
- 一个程序员的顿悟:理想的程序员只比你多了6个一点点
- mac上安装docker + tensor flow
- error the @annotation pointcut expression is only supported at Java 5
- Hbibernate 基础学习
- 位运算符—|
- 浏览器pdf文件预览的相关问题
- RHEL 6 安全加固与基础优化之三--V1.0-Mr.pan @树袋飘零
- datatables表格怎么控制小数点位数
- android参考 api文档
- Json数据解析
- 通过Sqoop实现Mysql / Oracle 与HDFS / Hbase互导数据
- 对XStream的实例应用2