hdu 4542 "小明系列故事——未知剩余系" (反素数+DFS剪枝)
参考资料:
[1]:https://blog.csdn.net/acdreamers/article/details/25049767
题意:
输入两个数 type , k;
①type = 0,求[1,262]中的因子个数为 k 的反素数,如果求解的答案 > 262,输出"INF";
②type = 1,求使得 num-factor[num] = k 的最小的num;
题解:
只有当 type = 1 时,才有可能输出 "Illegal";
那,什么情况下才会输出呢?
考虑一点,当 num 很大时,num-factor[num]也会随之变大,因为 k 最大为 47777,所以,对于type=1的情况,可以预处理出来;
1 int vis[maxn];//vis[i]:保存的是num-factor[num]=i的最小的num 2 void factorTable()//因子表 3 { 4 fill(factor,factor+maxn,1); 5 for(int i=2;i < maxn;++i) 6 { 7 if(factor[i] != 1) 8 continue; 9 for(int j=i;j < maxn;j+=i) 10 { 11 int k=0; 12 for(int m=j;m%i == 0;m/=i,k++); 13 factor[j] *= k+1; 14 } 15 } 16 mem(vis,INF);//初始为INF 17 for(int i=1;i < maxn;++i) 18 vis[i-factor[i]]=min(vis[i-factor[i]],i); 19 }
那么,当 type = 0 时,就和之前的题一个做法了,不过,需要剪枝才能过;
AC代码:
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define INF 0x3f3f3f3f 4 #define INFull ~0ULL 5 #define ll long long 6 #define ull unsigned long long 7 #define mem(a,b) memset(a,b,sizeof(a)) 8 const int maxn=1e5+50; 9 const ll maxV=(1ll*1<<62)+1; 10 11 int k,type; 12 int factor[maxn]; 13 int vis[maxn];//vis[i]:保存的是num-factor[num]=i的最小的num 14 int prime[16]={2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53}; 15 16 void factorTable()//因子表 17 { 18 fill(factor,factor+maxn,1); 19 for(int i=2;i < maxn;++i) 20 { 21 if(factor[i] != 1) 22 continue; 23 for(int j=i;j < maxn;j+=i) 24 { 25 int k=0; 26 for(int m=j;m%i == 0;m/=i,k++); 27 factor[j] *= k+1; 28 } 29 } 30 mem(vis,INF);//初始为INF 31 for(int i=1;i < maxn;++i) 32 vis[i-factor[i]]=min(vis[i-factor[i]],i); 33 } 34 /** 35 根据反素数的性质可知: 36 当前素数的指数要小于等于之前比起小的素数的指数 37 这就是limit的作用,剪枝1 38 初始为62(最大为2的62次幂) 39 */ 40 void DFS(int dep,int limit,ll curNum,int curK,ll &ans) 41 { 42 if(curK == k && curNum < ans) 43 ans=curNum; 44 45 for(int i=1;i <= limit;++i) 46 { 47 //向后遍历,i会增大,如果当前的 curK*(i+1) > k,那么之后的肯定也大于k 48 if(ans/curNum < prime[dep] || curK*(i+1) > k)//剪枝2 49 break; 50 51 curNum *= prime[dep]; 52 /** 53 如果curK*(i+1) = k,那么,势必组成curK的所有的(i+1)都为k的因子 54 例如: 55 假设k=(p1+1)*(p2+1)*......*(pn+1) 56 那么k%(p1+1)=0,k%(p2+1)=0,....,k%(pn+1)=0; 57 */ 58 if(k%(curK*(i+1)) == 0)//剪枝3 59 DFS(dep+1,i,curNum,curK*(i+1),ans); 60 } 61 } 62 void Solve() 63 { 64 if(type)//type = 1 65 { 66 if(vis[k] == INF)//判断是否有解 67 printf("Illegal\n"); 68 else 69 printf("%d\n",vis[k]); 70 return ; 71 } 72 ll ans=maxV; 73 DFS(0,62,1,1,ans); 74 if(ans >= maxV) 75 printf("INF\n"); 76 else 77 printf("%lld\n",ans); 78 } 79 int main() 80 { 81 // freopen("C:\\Users\\hyacinthLJP\\Desktop\\in&&out\\contest","r",stdin); 82 factorTable(); 83 int test; 84 while(~scanf("%d",&test)) 85 { 86 for(int i=1;i <= test;++i) 87 { 88 scanf("%d%d",&type,&k); 89 printf("Case %d: ",i); 90 Solve(); 91 } 92 } 93 return 0; 94 }