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;
}
浙公网安备 33010602011771号