zoukankan      html  css  js  c++  java
  • 数论---------------基本数论

    数论

    题目描述

    给定正整数 n,k,已知非负整数 x满足 n! mod k^x=0,求最大的x为多少? 输入格式本题包含多组数据,请处理至文件末尾。对于每组数据,共有一行,两个整数,表示 n,k。 输出格式对于每组数据,输出一行,一个整数,表示 最大的x。

     输入样例

    10 2
    5000000000000000000 2
    5000000000000000000 10000000000000

    输出样例

    8

    4999999999999999981

    96153846153846153

    数据范围与提示

    对于 40%的数据,k<=2×10^7,n<=2×10^9,数据组数<=50。

    对于 100%的数据,1<k<=10^13,1<=n<=5×10^18,数据组数 <=200。


      

    数论基本操作:唯一分解定理。

          第一点,像这种只给两个数的数论题,我们先寻找切入点,k 比较小。

          第二点,思路就是看答案“长什么样”。

                 • 显然答案可以写成 n!= p *(k ^ x)  ,需要最大化 x 。

                 • 那么 x 是受到什么的限制呢?

                    • 分解他们会发现显然的一个条件:对于每一的质数q,我们假设  n!最多能够分解出 a 个 q ,

                 而 k 能够分解出 b 个 q 。显然 a >= b * x 。                          

          接下来就明确目的了,我们可以在 √k 的时间内分解 k (不过多组数据建议预处理素数)

              • 然后需要知道 n!能分解出多少个对应的素数,那我们反着考虑每个素数 ,就可以在很快

                的时间内算出答案了。

     1 #include<bits/stdc++.h>
     2 #define ll long long
     3 using namespace std;
     4 int top;
     5 ll n,k,m,tmp,ans,tot,t[100],sum[100];
     6 ll p[2000050],cnt;
     7 bool vis[4000050];
     8 void calc()
     9 {
    10     for(int i=2;i<=4000000;++i)
    11     {
    12         if(!vis[i])
    13             p[++cnt]=i;
    14         for(int j=1;j<=cnt;++j)
    15         {
    16             tmp=(ll)p[j]*i;
    17             if(tmp>4000000)
    18                 break;
    19             vis[tmp]=true;
    20             if(i%p[j]==0)
    21                 break;
    22         }
    23     }
    24 }
    25 int main()
    26 {
    27     calc();
    28     while(scanf("%lld%lld",&n,&k)!=EOF)
    29     {
    30         m=sqrt(k);top=0;
    31         ans=6999999999999999999;
    32         for(int i=1;p[i]<=m;++i)
    33             if(k%p[i]==0)
    34             {
    35                 ++top;
    36                 t[top]=p[i],sum[top]=0;
    37                 while(k%p[i]==0)
    38                 {
    39                     k/=p[i];
    40                     ++sum[top];
    41                 }
    42             }
    43         if(k>1)
    44         {
    45             t[++top]=k;
    46             sum[top]=1;
    47         }
    48         for(int i=1;i<=top;++i)
    49         {
    50             tot=0;tmp=n;
    51             while(tmp>=t[i])
    52             {
    53                 tot+=tmp/t[i];
    54                 tmp/=t[i];
    55             }
    56             ans=min(ans,tot/sum[i]);
    57         }
    58         printf("%lld
    ",ans);
    59     }
    60     return 0;
    61 }
    代码
  • 相关阅读:
    Java操作excel,读取及导出
    vue 在package.json配置对外暴露访问地址(手机端访问本地项目地址)
    element UI upload组件上传附件格式限制
    linux之vim/vi快速复制多行内容的快捷键
    使用vant的Toast组件时提示not defined
    如何使用js判断当前页面是pc还是移动端打开的
    JavaScript 保留两位小数函数
    Linux其他命令
    linux学习ls的三个选项 lha的作用和隐藏文件的知识
    vue+ element-ui el-table组件自定义合计(summary-method)坑
  • 原文地址:https://www.cnblogs.com/wyher/p/9815758.html
Copyright © 2011-2022 走看看