zoukankan      html  css  js  c++  java
  • 因数(factor)

    一个最基本的算数法则就是大于1的整数都能用1个或多个素数相乘的形式表示出来。当然,有多种质因子排列方案

    如:

    10=2×5=5×2    20=5×2×2=2×5×2=2×2×5

    用f(k)表示k的质因数排列数,f(10)=2,f(20)=3

    给一个n,至少有一个k满足f(k)=n的最小k

    输出格式:n和k

    输入:

    1

    2

    3

    105

    输出:

    1 2

    2 6

    3 12

    105 720

    数据范围

    n,k<2^63

    我们令k=∏piei

      S=∑ei

    f(k)=S!/(∏ei!)

    解释一下:S是所有因数的个数,ei是每一种因数的个数

    显然不考虑重复的情况时方案为S!

    那么算上重复的会怎样?

    1112是已定的

    如果是算总方案显然4!,那么111会导致的重复方案是3!2导致的重复方案为1!

    所以有了以上结论

    那么我们有了一种方法:枚举k得到n

    显然不行

    那么是否可以试一下已知n,得到k?

    已知对于一个指数e,如果在可行条件下,那么它显然优先给最小的质因数,这能导致k最小

    搜索+剪枝实现

    剪枝1:上面说的优先给小的素数,就是说ei要单调递增,因为如果ei>ej,i>j,那么显然把ei与ej

    交换才能最优

    剪枝2:假设你每举了t素数的指数e

    就要把n除以 ((S-e+1)*...*S) /e!

    如何高效算出?

    原式=>S!/(e!*(S-e)!)

    这不就是C(S,S-e)吗?

    预处理出C,然后每一层枚举一个素数的指数,然后向下

    剪枝3:最优性剪枝,当前k>ans 则退出

    预处理幂不说了

    但记住无论是幂,还是k,都不能超过(1<<63)-1

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 using namespace std;
     6 int pr[15]={2,3,5,7,11,13,17,19,23,29,31,37,41,43,47};
     7 long long pw[15][64],C[64][64],ans;
     8 long long inf;
     9 long long min(long long a,long long b)
    10 {
    11   if (a<b) return a;
    12   else return b;
    13 }
    14 void dfs(int t,long long now,long long pre,long long s,int down)
    15 {
    16   if (s>ans) return;
    17   if (now==1)
    18     {
    19       ans=min(ans,s);
    20       return;
    21     }
    22   if (t>14) return;
    23   for (int i=pre+1;i<=min(pre+down,62);i++)
    24     if (now%C[i][i-pre]==0&&pw[t][i-pre]&&s<=inf/pw[t][i-pre])
    25       dfs(t+1,now/C[i][i-pre],i,s*pw[t][i-pre],i-pre);
    26 }
    27 void ask_ans(long long k)
    28 {
    29   ans=inf;
    30   dfs(0,k,0,1,62);
    31   ans=max(ans,2);
    32 }
    33 int main()
    34 {int i,j,k;
    35   freopen("factor.in","r",stdin);
    36   freopen("factor.out","w",stdout);
    37   C[0][0]=1;
    38   for (i=1;i<64;i++)
    39     {
    40       C[i][0]=C[i][i]=1;
    41       for (j=1;j<i;j++)
    42         C[i][j]=C[i-1][j-1]+C[i-1][j];
    43     }
    44   for (i=0;i<=14;i++)
    45     {
    46       pw[i][0]=1;
    47       for (j=1;j<=63;j++)
    48     {
    49       if (i&&pw[i][j-1]>inf/pr[i]) break;
    50       pw[i][j]=pw[i][j-1]*pr[i];
    51     }
    52       if (i==0)
    53     inf=pw[0][63]-1;
    54     }
    55   while (cin>>k)
    56     {
    57       ask_ans(k);
    58       cout<<k<<' '<<ans<<endl;
    59     }
    60 }
  • 相关阅读:
    “Win10 UAP 开发系列”之 在MVVM模式中控制ListView滚动位置
    “Win10 UAP 开发系列”之主题模式切换
    Windows Phone 8.1中AppBarToggleButton的绑定问题
    Windows Phone 8.1中处理后退键的HardwareButtons.BackPressed事件
    在后台代码中动态生成pivot项并设置EventTrigger和Action的绑定
    数据对象转json与md5加密注意事项
    iOS中wkwebview加载本地html的要点
    iOS项目开发常用功能静态库
    AFN中请求序列化的设置
    swift中的AnyHashable
  • 原文地址:https://www.cnblogs.com/Y-E-T-I/p/7521413.html
Copyright © 2011-2022 走看看