洛谷的八连测中,R1和R3可以在比赛中搜到,即使你没有交费报名八连测,这两次测试也是可以做的,题目都还不错,里面的题解也都很清晰,各位和我一样的提高组蒟蒻也完全可以自己做。
这里我要讲的题便是八连测中的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;
}