hdu 4542 小明系列故事——未知剩余系

小明系列故事——未知剩余系

题意:操作0表示某数有n个约数,操作1为某数有n个非约数;n <= 47777,若是存在小于2^62的数符合,则输出该数,否则若是不存在输出Illegal,若是大于2^62输出INF;

Sample Input
3
0 3
1 3
0 10
 
Sample Output
Case 1: 4
Case 2: 5
Case 3: 48
 
思路:对于确定的约数个数(操作0),可以直接建搜索树,深搜即可;里面用了剪枝优化,即当素因子从小到大排序时,指数不递增;还有就是由于各个不同的质因数的指数是按照乘法原理得到最终的约数的,所以每次得到的约数必须能整除最终的约数个数;
对于操作1来说,看了Acdreams的,里面并没有证明为什么直接可以递推到比最大约数个数47777大一些的50005既可以确定d[i]为0时,后面就不可能在出现非约数个数为i的数了;我也没有证明出来...
时间复杂度为O(nlog(n)) 15ms
 
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string.h>
#include<algorithm>
#include<vector>
#include<cmath>
#include<stdlib.h>
#include<time.h>
#include<stack>
#include<set>
#include<map>
#include<queue>
using namespace std;
#define rep0(i,l,r) for(int i = (l);i < (r);i++)
#define rep1(i,l,r) for(int i = (l);i <= (r);i++)
#define rep_0(i,r,l) for(int i = (r);i > (l);i--)
#define rep_1(i,r,l) for(int i = (r);i >= (l);i--)
#define MS0(a) memset(a,0,sizeof(a))
#define MS1(a) memset(a,-1,sizeof(a))
#define MSi(a) memset(a,0x3f,sizeof(a))
#define lson l, m, rt << 1
#define rson m+1, r, rt << 1|1
typedef pair<int,int> PII;
#define A first
#define B second
#define MK make_pair
typedef __int64 ll;
template<typename T>
void read1(T &m)
{
    T x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    m = x*f;
}
template<typename T>
void read2(T &a,T &b){read1(a);read1(b);}
template<typename T>
void read3(T &a,T &b,T &c){read1(a);read1(b);read1(c);}
template<typename T>
void out(T a)
{
    if(a>9) out(a/10);
    putchar(a%10+'0');
}
const int N = 50005;
typedef unsigned long long ull;
const ull inf = (1ULL<<62);
int d[N];
void init()
{
    rep1(i,1,N) d[i] = i - 1;
    rep0(i,2,N){
        for(int j = i;j < N;j += i)
            d[j]--;
        if(!d[d[i]]) d[d[i]] = i;
        d[i] = 0;
    }
    //rep1(i,1,100)if(d[i] == 0){cout<<i<<" ";}
}
int p[16] = {2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53};
int n;
ull ans;
void dfs(int dept,ull val,int num,int last)
{
    if(num > n || n%num) return ;
    if(num == n){
        ans = min(ans,val);
        return ;
    }
    for(int i = 1;i <= last;i++){
        if(ans/p[dept] <= val) break;
        dfs(dept+1,val *= p[dept],num*(i+1),i);
    }
}
int main()
{
    int kase = 1,T,op;
    init();
    read1(T);
    while(T--){
        read2(op,n);
        if(op & 1) ans = d[n];
        else{
            ans = inf + 1;
            dfs(0,1,1,62);
        }
        printf("Case %d: ",kase++);
        if(ans > inf) puts("INF");
        else if(ans == 0) puts("Illegal");
        else {out(ans);puts("");}
    }
    return 0;
}
View Code

 

posted @ 2016-03-09 17:18  hxer  阅读(303)  评论(0编辑  收藏  举报