hdu4542 && ZOJ2562(反素数)
反素数:
对于任何正整数,其约数个数记为,例如,如果某个正整数满足:对任意的正整
数,都有,那么称为反素数。
有两个特点:
1.一个反素数的质因子必是从2开始的质数
2.如果,那么必有
最常见的问题如下:
(1)给定一个数,求一个最小的正整数,使得的约数个数为
(2)求出中约数个数最多的这个数
即是通过搜索建立一个搜索树,递归出合适的所有的情况,再加上剪枝。
ZOJ2562
题意:
给定一个数N,求小于等于N的所有数当中,约数最多的一个数,如果存在多个这样的数,输出其中最大的一个。
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include <cmath> #include <time.h> #define N 10100 typedef long long ll; using namespace std; ll maxs,allnum; ll n; int prim[16] = {1,2,3,5,7,11,13,17,19,23,29,31,37,41,43,47}; void dfs(ll num,ll k,ll sum,ll limit) { if(sum > maxs) { maxs = sum; allnum = num; } if(sum == maxs && allnum > num ) allnum = num; ll temp = num; if(k > 15) return ; for(int i= 1;i <= limit;i++) { if(temp*prim[k] > n) break; dfs(temp*= prim[k],k+1,sum*(i+1),i); } } int main() { while(cin>>n) { maxs = 0; allnum = n; dfs(1,1,1,50); cout<<allnum<<endl; } return 0; }</span>
hdu 4542
题意:
给出一个数K,和两个操作,
如果操作是0,就求出一个最小的正整数X,满足X的约数个数为K,
如果操作是1,就求出一个最小的X,满足X的约数个数为X-K。
d来先处理成与i互质的个数。由于d[i] < i,将其处理成d[i]=x,表示有x 个非约数的为i
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include <cmath> #include <time.h> #define N 10100 typedef long long ll; using namespace std; ll INF = ((ll)1<<62)+1; int d[50005]; ll maxs,allnum; ll n,type; int prim[16] = {2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53}; void ini() { for(int i = 1; i <= 50005; i++) d[i] = i; for(int i = 1; i <= 50005; i++) { for(int j = i; j <= 50005; j+=i) d[j]--; //滚动数组的形式 if(!d[d[i]]) d[d[i]] = i; d[i] = 0; } } //如果d[k]=0,表示小于i的所有数中,没有刚好有k个互质数的数 //故将d[k]=i,表示刚好有k个与i互质的数个数最小为i //d[i] = 0标记刚好有k个互质数的数没有 void dfs(ll sum,ll k,ll num,ll limit) { if(num > n) return ; if(sum < maxs && num == n) maxs = sum; ll temp = sum; for(int i= 1; i <= limit; i++) { if(num*(i+1) > n || maxs/prim[k] < temp) break; //大于n或者结果大于maxs,不需再考虑 temp *= prim[k]; if(n % (num*(i+1)) == 0) dfs(temp,k+1,num*(i+1),i); } } int main() { int T; int tt = 1; ini(); scanf("%d",&T); while(T--) { scanf("%I64d%I64d",&type,&n); if(type) maxs = d[n]; else { maxs = INF; dfs(1,0,1,100); //最初这100是50,,一直错,估计是太小 } printf("Case %d: ",tt++); if(maxs == 0) puts("Illegal"); else if(maxs >= INF) puts("INF"); else printf("%I64d\n",maxs); } return 0; }