洛谷2017年10月八连测R1 T1 :一道中档题 Factorial 解题报告

洛谷的八连测中,R1R3可以在比赛中搜到,即使你没有交费报名八连测,这两次测试也是可以做的,题目都还不错,里面的题解也都很清晰,各位和我一样的提高组蒟蒻也完全可以自己做。

这里我要讲的题便是八连测中的R1T1,在此附上题目网址

(传送门:题目https://www.luogu.org/problemnew/show/P3927

这道题思路其实来源于我们手推进制转换的过程,利用了短除法(例子讲解)

由此我们可知:当n可被k^m整除且m最大时,十进制数n的k进制数末尾就有m个0

因此,我们需要将k分解质因数,每当n!的因数(即1*...*n)中每个数的质因数组成中能凑出来一套k的质因数组成,m(初值为0)就能在原来的基础上加1,最后输出m即可

所以我们需要利用三重循环在1,...,n-1,n中依次查找每一个k的质因数组成,得出来的个数再除以k中此质因数的组成个数。将每一个k中质因数所查找得出的套数进行比较,找出最小的一个套数输出(木桶效应)

这是解决本道题的最基础的思想,想到这,能得40分,60分的点全部TLE

40分代码如下:

#include<stdio.h>
int p[100001],num[100001];
int main()
{
    long long int tot=0,n,k,min=2147483647,cnt=1;
    scanf("%lld%lld",&n,&k);
    while(k>1)
    {
     ++cnt;
     if(k%cnt==0)p[++tot]=cnt;
     while(k%cnt==0)
     {
      num[tot]++;
      k/=cnt;
     }
    }
    for(long long int i=1;i<=tot;i++)
    {
     long long ans=0;
     for(long long int j=1;j<=n;j++)
     {
      long long nn=j;
      while(nn%p[i]==0)
      {
       nn/=p[i];
       ans++;
      }
     }
     ans/=num[i];
     if(ans<min)min=ans;
    }
    printf("%lld",min);
    return 0;

而要AC,我们就必须知道一个道理:

由于n!是1乘到n,所以每p(p是质数)个数里一定有一个p,然后这些数中每p个里一定还有个p,以此类推即可算出m。这种方法,我们每一次都能查找到含有p为质因数的数并累计个数。将三重循环简化为二重循环

100分代码如下:

#include<stdio.h>
int p[100001],num[100001];
int main()
{
long long int tot=0,n,k,min=200000000000000,cnt=1;
scanf("%lld%lld",&n,&k);
for(cnt=2;k>1&&cnt<=k;cnt++)
{
if(k%cnt==0)p[++tot]=cnt;
while(k%cnt==0)
{
 num[tot]++;
 k/=cnt;
}
}
for(long long int i=1;i<=tot;i++)
{
long long ans=0,nn=n;
while(nn>0)
{
 ans+=nn/p[i];
 nn/=p[i];
}
ans/=num[i];
if(ans<min)min=ans;
}
printf("%lld",min);
return 0;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值