HDOJ 4542 小明系列故事——未知剩余系(反素数)

来源:互联网 发布:c语言比较三个数大小 编辑:程序博客网 时间:2024/06/01 09:17


http://acm.hdu.edu.cn/showproblem.php?pid=4542


题意:当type = 0, 求约数有k个的最小整数,当type = 1, 求非约数有k个的最小整数。


首先考虑type = 0 的情况


反素数的定义:对于任何正整数,其约数个数记为,例如,如果某个正整数满足:对任意的正整

            数,都有,那么称为反素数。

 

从反素数的定义中可以看出两个性质:

 

(1)一个反素数的所有质因子必然是从2开始的连续若干个质数,因为反素数是保证约数个数为的这个数尽量小

(2)同样的道理,如果,那么必有


反素数为什么是保证约数个数为x的这个数n尽量小?如果有n1>……>n2,f(n1)=……=f(n2)=k,那么根据定义,n2才可能是反素数。(可能不是的原因是f(i)>f(n))

如果反素数的质因子不是连续的,那么必然有一种约数个数为x的连续情况(可以看成是指数不变,底数全部向前挪),所得的n一定比当前的小,违反了保证约数个数为x的这个数n尽量小。

如果不是t1>=t2>=t3……这样的不上升序列,那么约数个数为x的这个数n还不是最小的,同样也违反了。

约数个数为x的最小数n,一定满足(1)(2),但反之也不一定成立。

所以反素数一定满足(1)(2),但反之不一定成立。

题目中type = 0的情况,是求一个最小的数使它的约数个数为k,那么就是在满足(1)(2)的数中找最小的。可以用dfs。

type = 1时 ip[i]本来是表示i的非约数个数 后来改成了非约数个数为i的最小数为ip[i]

#include<cstdio>#include<cstring>#include<cmath>#include<algorithm>#define LL __int64#define N 50005using namespace std;const int p[16] = {2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53};const LL INF = (((LL)1)<<62)+1;LL ans;int ip[N], k;void Init(){    for(int i=1;i<N;i++) ip[i] = i;    for(int i=1;i<N;i++)    {        for(int j=i;j<N;j+=i) ip[j]--;        if(!ip[ip[i]]) ip[ip[i]] = i;        ip[i] = 0;                                                                                                                   }                                                                                                                             }void dfs(LL dept, LL limit, LL tmp, LL num) //当前处理第dept个质因子,limit是根据规律在限制指数,tmp是当前已累乘的数,num是当前已经产生了多少个约数 约数个数是同一个质因子出现个数+1累乘{    if (num == k && tmp < ans) ans = tmp;    for (int i = 1; i <= limit; i++)    {        if (ans / double(p[dept]) <= tmp || num * (i+1) > k) break; // 不能写成 ans < tmp*p[dept] 会爆LL        tmp *= p[dept];        if (k % (num * (i+1)) == 0)            dfs(dept+1, i, tmp, num * (i+1));    }}int main(){    Init();    LL tt = 1, n;    scanf("%I64d", &n);    while (n--)    {        LL T;        scanf("%I64d%I64d", &T, &k);        if (T == 1) ans = ip[k];        else        {            ans = INF;            dfs(0, 62, 1, 1);        }        printf("Case %I64d: ",tt++);        if (ans == 0)            printf("Illegal\n");        else if (ans >= INF)            printf("INF\n");        else printf("%I64d\n", ans);    }    return 0;}






0 0