http://acm.hdu.edu.cn/showproblem.php?pid=4542
这个题 type 为 0 和 type 为 1 的求解方法居然没有什么关系,无语
对于 type 为1 的情况:
可以发现随着x的增大[1~x]中不是x的约数的数也基本上是增大的
所以可以开一个比较大的数组,用求解素数的思路求出每个数中它的非约数的个数
然后找到某个数量第一次出现的x 如果没有出现,就可以简单的认为是没有这种情况
对于type为0的情况:
必须先知道一点
假设P(i)代表某个素数a(i)代表这个素数的幂
那么任何一个数都可以分解成 ( P(1)^a(1) )*( P(2)^a(2) )*( P(3)^a(3) )*.............*( P(k)^a(k) )
而且这个数的约数的数量为 (a(1)+1)*(a(2)+1)*(a(3)+1)*.............*(a(k)+1)
在这种情况下开一个二维数组进行DP就可以了
代码:
#include<iostream> #include<cstdio> #include<cstring> #include<string> #include<map> #include<set> #include<vector> #include<stack> #include<queue> #include<algorithm> #include<cmath> #define LL long long #define ULL unsigned long long using namespace std; const int INF=0x3f3f3f3f; const LL LINF=ceil(pow(2.0,62)); const double DINF=(pow(2.0,62)); const int N=100005; const int M=17; const int K=50000; int a[N],b[N]; int p[]={1,2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53}; LL dp[M][K]; int main() { //freopen("data.in","r",stdin); memset(dp,-1,sizeof(dp)); LL tmp=1; for(int j=0;j<63;++j) { dp[1][j+1]=tmp; if(double(tmp)*double(p[1])>DINF) break; tmp=tmp*p[1]; } for(int i=1;i<M-1;++i) for(int j=1;j<K;++j) if(dp[i][j]!=-1) { tmp=p[i+1]; for(int l=1;l<63;++l) { if(double(dp[i][j])*double(tmp)>DINF) break; int r=j*(l+1); if(r>=K) break; if(dp[i+1][r]==-1||dp[i+1][r]>dp[i][j]*tmp) dp[i+1][r]=dp[i][j]*tmp; if(double(tmp)*double(p[i+1])>DINF) break; tmp=tmp*p[i+1]; } } for(int i=1;i<N;++i) a[i]=i; memset(b,-1,sizeof(b)); for(int i=1;i<N;++i) for(int j=i;j<N;j=j+i) { --a[j]; if(b[a[i]]==-1) b[a[i]]=i; } int T; scanf("%d",&T); for(int w=1;w<=T;++w) { int k,n; scanf("%d %d",&k,&n); printf("Case %d: ",w); if(k==1) { if(b[n]==-1) printf("Illegal\n"); else printf("%d\n",b[n]); }else { LL ans=-1; for(int i=1;i<M;++i) if(dp[i][n]!=-1) { if(ans==-1||dp[i][n]<ans) ans=dp[i][n]; } if(ans==-1||ans>LINF) printf("INF\n"); else cout<<ans<<endl; } } return 0; }