TIMUS-1748. The Most Complex Number-求反素数(数学+搜索)

来源:互联网 发布:国家网络风险评估标准 编辑:程序博客网 时间:2024/05/21 08:56

http://acm.timus.ru/problem.aspx?space=1&num=1748

 

题意:给定一个数n,要求一个不超过n的数,并且因子数最多的最小的数。

也就是反素数

根据反素数的性质,每个反素数必然是由一系列【连续】质因子组成,并且较小的因子的次数一定比较大的因子的次数大 (不满足这两个条件必然可以找到一个 更小的数 且因子数与该数相同 ,矛盾)


所以我们dfs搜即可。

搜索控制两个条件

1:第k个因子的最高次比k-1的最高次低

2:因子数的话,可以根据 定理1: 一个正整数 n 可以用***素***因子唯一表示为 p1^r1 * p2^r2 * ... pk^rk (其中 pi 为素数) , 那么这个数的因子的个数就是,(r1+1)*(r2+1)~(rk+1).来求



搜索过程的话,如果发现当前乘积已经大于n了,就可以break掉

本题数据比较大。 这个判断用乘法会溢出,所以改用除法就好了



0.28s

#include <cstdio>#include <cmath>#include <cstring>#include <string>#include <algorithm>#include <queue>#include <map>#include <set>#include <vector>#include <iostream>using namespace std;#define ll __int64#define ull unsigned __int64const double pi=acos(-1.0);double eps=0.000001;int prime[]={1,2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53};ll ans;ll num;ll n;void dfs(int k, ll now,ll cnt,int last)//求1-n最大反素数,初始化ans=n,num=1//k是层数,now是当前的乘积,cnt是当前的数对应的因子数,last是最后一个因子的最高次数{ if (now>n) return; //剪枝,比判k==17快//if (k==17) return ;if ( cnt>num)//更新答案{ ans=now;num=cnt;}elseif(cnt==num){if (now<ans)ans=now;} ll t=prime[k],i;//t是素因子的方幂for (i=1;i<=last;i++)//last是最高次,显然当前素因子最高次不超过前面的最高{if (t>n/now) break;//乘法溢出dfs(k+1,now*t,cnt*(i+1),i);t*=prime[k]; }}int main(){int t;cin>>t;while(t--){num=1;scanf("%I64d",&n);ans=n;dfs(1,1,1,60);printf("%I64d %I64d\n",ans,num);}return 0;}


0 0
原创粉丝点击