zoj 3621(详解 数论)

    原创:转载请注明出处::http://blog.csdn.net/u014686462/article/details/37889583


     看了几篇博文加题解,还是无法弄懂代码的含义。所以自己慢慢推,输出中间结果,终于知道啥回事了。

首先思路就是找K的所有质因子存在数组 p[cnt]里 ,该质因子的个数存在数组 num[cnt]里,对每num[i] 个质因子 p[i],

看N!能贡献多少组这样的。最终得到的最小组数就为答案。

  举个例子:

N=1200  K=10

先看看p与num数组里存了些什么。明显有:

//因为10=2*5
  p[1]=2,num[1]=1;
  p[2]=5,num[2]=1;
然后对于每个质因子,看N!能贡献多少个。

  p[1]=2;
  1200/2=600;//首先贡献了600个2,参与贡献的数来自于1*2,2*2,3*2,4*2,...600*2(达到了上限)
  600/2=300;//然后把上面每个数都除2,所以就是1到600,按照相同的算法,可以贡献300个2.
  ....
  ...
  .
  把所有的贡献个数加起来就知道了1200!贡献了1196个2;
  同理....
  p[2]=5;
  1200/5=240;
  ...
  ..
  把所有的贡献个数加起来就知道了1200!贡献了298个5;
  因为1个2乘1个5才有10,所以最终就是298个0;
过程就是这样的,举个例子然后相信大家都看懂了吧!

最后上代码:

#include<iostream>
#include<algorithm>
#include<map>
#include<string>
#include<cstdio>
#include<string>
#include<cstring>
#include<cmath>
using namespace std;
int p[20],num[20],N;
long long pn[20];
void ph(int x)//对x分解质因子
{
    int i;
    N=0;
    memset(num,0,sizeof(num));
    memset(p,0,sizeof(p));
    for(i=2;i<(int)sqrt(x*1.0)+1;i++)
    {
        if(x%i==0)
        {
            while(x%i==0)
            {
                num[N]++;
                x/=i;
            }
            p[N++]=i;
        }
    }
    if(x>1)
    {
        num[N]++;
        p[N++]=x;
    }
}
void eul(long long x)//对于每个质因子,看N!能贡献多少个。
{
    int i;
    long long res=x;
    memset(pn,0,sizeof(pn));
    for(i=0;i<N;i++)
    {
        res=x;
        res=res/p[i];
        pn[i]=res;
        while(res)//就是在不断地除质因子
        {
            res=res/p[i];
            pn[i]+=res;
        }
    }
}
int main()
{
    long long a,n;
    char s[100];
    int b,i;
    while(scanf("%s%d",s,&b)!=EOF)
    {
        a=0;
        for(i=0;i<(int)strlen(s);i++)
        {
            if(s[i]>='A'&&s[i]<='Z')  a=a*b+s[i]-'A'+10;
            else if(s[i]>='a'&&s[i]<='z')  a=a*b+s[i]-'a'+36;
            else a=a*b+s[i]-'0';
        }
        ph(b);
        eul(a);
        n=-1;
        for(i=0;i<N;i++)
        {
            if(n>pn[i]/num[i]||n==-1)//找最小的贡献数
                n=pn[i]/num[i];
        }
        printf("%lld\n",n);
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值