您的位置:首页 > 其它

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

2017-07-19 13:13 197 查看
点击打开题目链接


题目是中文题目,但是还是有点绕的。

题目意思:

每次给出两个数 Type,K.

Type = 0        求因子的个数为K的最小整数X,如果这个数大于2^62次方,输出INF,否则输出答案

Type = 1        求因子个数为X-K的最小整数X.

第一问其实就是求解因子个数为K的反素数。套求反素数的模板

因为最近做了一个题POJ 2886 要用到反素数这个概念,但是自己之前都不知道这个东西,只能先学反素数在做这个踢了,所以就去别人博客学习了一下

反素数的概念和来做了两道题。反素数的概念

第二问,求一个最小的X,其因子个数为X-K,则1~X中其因子个数为K

这个是看别人的题解,求解方法挺巧妙的,一开始还没看懂,不过后来就明白了,采用的方法是打表,设置数组,d[  ]

最开始d[i]初始化为i,在1~i中,i的因子个数为i-k,则i的非因子个数为K,因此对于i来说,i的倍数都要减去1,减去i这个因子

当求出d[i[后,d[i]代表1~i中i的非因子个数。如果d[d[i]] == 0 ,d[d[i]] = i ,直接将d[i]与i映射。然后让d[i] = 0。代表这个位置所

映射的答案还未找出。

AC代码:

#include <iostream>
#include <stdio.h>

using namespace std;

typedef unsigned long long ull;
#define INF ((ull)1)<<62
const int maxn = 50000;
ull ans;
int Type,K;
int d[maxn];   ///d[i]存放的是非约数个数为k的最小数值。
///制素数表
int prime[] = {2,3,5,7,11,13,17,19,23,29,31,37,41,47,53};
///这里难理解,看别人的好久才明白,只能说很巧妙
void create_table()
{
///d[i]最先存储的是i的非因子的个数
for(int i = 1; i < maxn; i++)
d[i] = i;
for(int i = 1; i < maxn; i++)
{
for(int j = i; j < maxn; j += i)
d[j]--;   ///i的倍数都要减减
///第i个数的非因子个数已经求出
if(!d[d[i]])
d[d[i]] = i;
/**这一步原来d[i]存放的是1~i内对于i的非因子个数为K,
如果d[k]的位置没有数,则当前i值就是答案,否则i是从小到大进行循环的,
如果d[K]的位置不等于0,说明之前已经有数占据这个位置了,那个数还比当前
i小,不用更新。每次都把d[i]赋值为0**/
d[i] = 0;
}
}
///求因子个数为K的最小数x,即求反素数
void dfs(int pos,ull value,int num)
{
if(num > K || pos > 15)
return;
if(num == K)
{
ans = min(ans,value);
return;
}
for(int i = 1; i <= 63; i++)
{
if(value > ans/prime[pos] || num*(i+1)>K)
break;
value *= prime[pos];
if(K%(num*(i+1))==0)
dfs(pos+1,value,num*(i+1));
}
}
int main()
{
int T,t=1;
create_table();  ///先打表
cin>>T;
while(T--)
{
cin>>Type>>K;
cout<<"Case "<<t++<<": ";
///求约数个数为X-K的最小X
if(Type)
{
if(d[K])
cout<<d[K]<<endl;
else
cout<<"Illegal"<<endl;
}
else
{
ans = 1e19;
dfs(0,1,1);
if(ans > INF)
cout<<"INF"<<endl;
else
cout<<ans<<endl;
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: